[今さら]C言語でクラスライブラリを作る[Cかよ]

このエントリーをはてなブックマークに追加
1デフォルトの名無しさん
C言語でOO的に使えるクラスライブラリを作ります。
OOに慣れてしまって今さら手続き型言語で設計できないorやりたくないのに、
Cで仕事しないといけない、そんなときにちょっと楽ができたらいいなと。

「Cで無理矢理OOすんな」とか言わないでね。
2デフォルトの名無しさん:2006/09/13(水) 09:46:01
Cで無理矢理OOすんな
3デフォルトの名無しさん:2006/09/13(水) 09:47:24
#ifndef _LINKMAP_H_
#define _LINKMAP_H_

typedef struct __entry {
char *key;
void *value;
struct __entry *next;
} entry_t;

typedef struct __linkMap {
entry_t *firstEntry;
entry_t *lastEntry;
void (*put)(struct __linkMap *this, const char *key, void *value);
void* (*get)(struct __linkMap *this, const char *key);
void (*destructor)(struct __linkMap *this);
} linkMap_t;


extern linkMap_t *linkMap_newInstance();

#endif //_LINKMAP_H_
4デフォルトの名無しさん:2006/09/13(水) 09:52:59
上のはlinkMap.hです。さっそく改行が多いとおこられたので
コメント削りました。こりゃlinkMap.cは無理だな。
こんな風に使えます。

linkMap_t *map1 = linkMap_newInstance();
linkMap_t *map2 = linkMap_newInstance();
map1->put(map1, "key1", "value1");
map1->put(map1, "key2", "value2");
map2->put(map2, "key1", map1->get(map1, "key1"));

これを利用したconfigクラスやloggerクラスがあります。
ソースアップするところは別に考えます。
5デフォルトの名無しさん:2006/09/13(水) 09:58:21
インターフェースですが、デストラクタコールがmap2->destructor(map2);
なのがおかしいよね。
コンストラクタとデストラクタはこんな風にした方がいいかなと
思ってるんだけどどうだろう

LinkMap map = new_LinkMap();
delete_LinkMap(map);

あとc++でいうthisポインタを渡すのに、いちいち自信のインスタンスを
引数で渡しているところが冗長で嫌なんだけど、Cでやる以上
仕方ないのかなあ
6デフォルトの名無しさん:2006/09/13(水) 10:15:50
C++->Cへのいいpreprocessorを作れば?
71:2006/09/13(水) 10:24:10
それだ!


言い出しっぺがつくるの法則でお願いします。
つーかありそうだよね。
8デフォルトの名無しさん:2006/09/13(水) 11:34:38
>>7
その調子で、お前はノリだけで生きてきたんだろうな。
そんなんじゃ、どんどんと出来る奴らに追い抜かれるだろうけど、それでいいのか?
9デフォルトの名無しさん:2006/09/13(水) 11:50:17
ぐだぐだ言ってないで、暇なら作ろう。
ちょっと昼休みした後、また再開する。
10デフォルトの名無しさん:2006/09/13(水) 12:08:34
glibみたく、外部インターフェースは
LinkMap_new
LinkMap_put
LinkMap_get
LinkMap_destroy
でいいじゃん。
明示的にthisポインタ渡すのは面倒すぎ。
111:2006/09/13(水) 12:15:41
http://www.s34.co.jp/cpptechdoc/article/oop_in_c/index.html
ここみたいにやった方がいいのかな
map->get(map, "key");
じゃなくて
linkMap_get(map, "key");
どっちもどっちだなあ。この方がメンバ変数にアクセスされないですむけど。

>>10
そのインターフェース例の場合、
インスタンスに対する操作なのかstaticな操作なのかは
引数の最初にthisポインタがあることで判断するってこと?

それとも明示的にthisポインタを渡さないで複数の
インスタンスを切り分ける別の方法をとるってこと?
インスタンスを特定するためのキーはなにか渡さないと
いけないわけでしょ?
12デフォルトの名無しさん:2006/09/13(水) 12:49:49
こんなのもあるけど、

http://www.sage-p.com/process/cool.htm

ObjC --> C のトランスレータ

http://users.pandora.be/stes/compiler.html

class, self, super くらいならプリプロセッサでナントカ
なるんじゃないの。
13デフォルトの名無しさん:2006/09/13(水) 12:52:37
>>11
書き方変だったな。
メソッドを参照するのと引数の二回、同じのを書くのが面倒って事で。

俺的お勧めは linkMap_get(map, "key"); の方かな。
struct __linkMap;
typedef struct __linkMap linkMap_t;
linkMap_t * LinkMap_new (void);
void LinkMap_destroy (linkMap_t *);
のように、構造体の中身を一切見せない、とかもできるし。
14デフォルトの名無しさん:2006/09/13(水) 12:55:48
・linkMapってナニ?
・それOOと何の関係が?
15デフォルトの名無しさん:2006/09/13(水) 12:58:46
C++からCへのトランスレータ使えば?
16デフォルトの名無しさん:2006/09/13(水) 12:58:59
17デフォルトの名無しさん:2006/09/13(水) 13:05:19
>>16
で、linkMapってナニ?
18デフォルトの名無しさん:2006/09/13(水) 13:08:50
OO ←これって何かの目?ですか?

Object Oppai の略ですか?
分かりません><;
19デフォルトの名無しさん:2006/09/13(水) 13:18:21
Ochinchin Okki
20デフォルトの名無しさん:2006/09/13(水) 13:21:00
ここはおまえの来るところじゃねーんだよ!
おまえ、かなり気持ち悪いから早く消えちまえ!

http://pc8.2ch.net/test/read.cgi/tech/1156661024/356-

356 名前: デフォルトの名無しさん 投稿日: 2006/09/13(水) 02:51:48
今更Cで仕事する羽目になったのですが、OOの癖が抜けなくてつらいです。
Cで使うOO風のライブラリってありませんか?
String *str = new_String("abc");
str->add("def");
みたいに書きたいんです。文字列の処理はString.hを見ればわかるっていう感じで
楽がしたいんです。Cではグローバルな関数群から目的のモノを探すだけで時間がかかります。

客(Solaris8)にコンパイルしてもらわなきゃいけないので、
大きくてトラブル対応できないライブラリは不可です。
見あたらなかったんでlinkMapとかloggerとか自分で作ってみたのですが、めんどくさく
なってきました。存在しないなら自作の奴をさらすので意見して欲しいなあと
思ってるんですがいかがでしょうか

363 名前: 356 [ssage] 投稿日: 2006/09/13(水) 08:29:31
10年以上前はCプログラマだった。 郷に入れば郷に従えだとは思うので、
c++で無理矢理Java風に書くのとかは嫌い。でも非OOで書くのはもうキツイ。
複数のインスタンスが生成できるコンテナあるのなら教えて。正直ググったけど
Hashtableのサンプルくらいしか見つからなかった。

Cで仕事することはもうほとんどないし、自作ライブラリよりもちゃんとメンテナの
いるライブラリを利用する方が効率いいからなあと思ったんだけど、
ちょっと別スレ建ててみますわ。まあスレが伸びなきゃ伸びないで終了ということで
21デフォルトの名無しさん:2006/09/13(水) 13:29:27
linkMapってJavaの方言か何か?
22デフォルトの名無しさん:2006/09/13(水) 13:34:08
JavaにはLinkedHashMapというのがあるが>1のlinkMapとの関連は不明。
23デフォルトの名無しさん:2006/09/13(水) 13:38:20
>>3を見る限り、単なるlink-list(linked-list)にしか見えないのだが・・・
24デフォルトの名無しさん:2006/09/13(水) 13:38:38

スレまで立てて、本当はヒマなんじゃねーの

こんなことするなら、自分で作って終わりでしょ

ていうか、そのスキルもなさそうだけどな

ケケケ
25デフォルトの名無しさん:2006/09/13(水) 13:43:16
つーか、そのlinkMapとやらは完成してるんだろ?
何がやりたいんだろう?
26デフォルトの名無しさん:2006/09/13(水) 13:52:09
「クラスライブラリ」ってどんなの想定してるんだろう。
27デフォルトの名無しさん:2006/09/13(水) 13:58:44
C 言語によるオブジェクト記述法 COOL
http://www.sage-p.com/process/cool.htm

COOLとプリプロセッサを駆使した
マクロテンプレートのコンテナとアルゴリズム
CPL
誰か作ってよ。
28デフォルトの名無しさん:2006/09/13(水) 14:08:24
「マクロテンプレートのコンテナとアルゴリズム」って何?
俺用語じゃ伝わらないよ。
29デフォルトの名無しさん:2006/09/13(水) 14:09:54
>>1
そんなくだらんこと考える暇があったら、checkでも使ってUnit Test書け
30デフォルトの名無しさん:2006/09/13(水) 14:47:17
>>20
>ここはおまえの来るところじゃねーんだよ!
いや、このスレで隔離できるものならそうして欲しい。
3127:2006/09/13(水) 15:15:54
>>28

こんなイメージ

#define CPL_VECTOR_VALUE_TYPE int
#define CPL_VECTOR_SIZE_TYPE size_t
#define CPL_VECTOR_ALLOCATOR malloc
#include<cpl/vector.h>

void test()
{
cpl_vector_int v;
cpl_vector_int_init(&v);

cpl_vector_init_push_back(100);

cpl_vector_int_finish();
}
32デフォルトの名無しさん:2006/09/13(水) 15:17:34
"CPL"って何だよ?

あー、イライラするwww
3327:2006/09/13(水) 15:17:48
cpl_vector_int_push_back(100);
修正w
34デフォルトの名無しさん:2006/09/13(水) 15:22:34
struct {
int count;
int* array;
}
でいいじゃん。
35デフォルトの名無しさん:2006/09/13(水) 15:23:56
隔離成功。
36デフォルトの名無しさん:2006/09/13(水) 15:25:04
>>4
別にメンバ関数のようなシンタックスにする必要はない
それはオブジェクト指向とは(本当は)関係がない

問題はデストラクタの自動呼出しに集中すると思う
37デフォルトの名無しさん:2006/09/13(水) 15:29:36
ポリモーフィズムを使いたいんでしょ
38デフォルトの名無しさん:2006/09/13(水) 15:32:35
(データ構造と手続きの)カプセル化とポリモルフィズムさえ出来ればOK。マクロとかで原型を留めないほどに置換しまくるんなら別にCじゃなくてもいいよ。Dとかあるし。

 typedef struct Map { void* instance; Map_Implementations* methods; } Map;
 typeaef struct Map_Implementations {
  void (*add)(self, Key* key, void* value);
  void* (*get)(Map* self, Key* key);
 } Map_Implementations;
 Map* mapNew(void* instance, Map_Implementations* methods) {
  Map* map = malloc(/*略*/);
  map->instance = instance;
  map->methods = methods;
  return map;
 }
 void mapAdd(Map* self, Key* key, void* value) { *(self->methods->add)(self->instance, key, value); }
 void* mapGet(Map* self, Key* key) { return *(self->methods->get)(self->instance, key, value); }
こんな感じで、インターフェースを定義しておいて、後で実装。
 typedef struct HashMap { ・・・; } HashMap;
 Map_Implementations methods = {
  // メソッドの登録。
 };
 Map* hashMapNew() {
  ・・・;
  return mapNew(self, &methods);
 }
 // メソッド実装の例
 void* mapGetImpl(HashMap* self, Key* key, void* value) {・・・; }
利用するときは・・・。
 Map* map = hashMapNew();
 mapAdd(map, "UNKO", "MANKO");
 puts(mapGet(map, "UNKO")); ==> MANKO
39デフォルトの名無しさん:2006/09/13(水) 15:33:36
モノポリーでもやってろカス
40デフォルトの名無しさん:2006/09/13(水) 16:16:47
「ポリ」しかおうてへんやんか!
41デフォルトの名無しさん:2006/09/13(水) 16:30:31
CoreFoundation使ってろカス
421:2006/09/13(水) 17:54:28
これもOOと関係ないけど、デストラクタの自動呼び出しもMapの実装の時に気になってた。
keyはchar*で受け取ってるからコピーしてMapのデストラクタで解放するけど、
valueの方はどうしたらいいんだろうって。勝手に解放しちゃまずいし、かといって
解放しないと同一keyで別のオブジェクトが登録されたときにメモリリークしてもまずいし。
スマートポインタ実装しようにも、ジェネリックがないからメンバメソッド呼出の度に
キャストしなきゃいけないし。あ、でもこれはインスタンスに対してメソッド呼び出し
というシンタックスにこだわらなきゃいけるか。

CoreFoundationはいいかも。>>41はカスとか言ってるけど一緒に勉強する
お友達が欲しかったんでしょ?もうちょっと見てみる。

43デフォルトの名無しさん:2006/09/13(水) 18:18:36
Java莫迦みたいだな
441:2006/09/13(水) 18:33:00
CoreFoundationをDLしようと思ったんだけど、AppleIDに登録して
ここから個別にDLするの・・??

http://www.opensource.apple.com/darwinsource/Current/CF-368.27/

調べてる時間あったらStringクラスとArrayクラスくらい書けたなあ

451:2006/09/13(水) 18:34:30
あ、ごめんtar.gzあったわ
46デフォルトの名無しさん:2006/09/13(水) 18:37:13
隔離完了。
47デフォルトの名無しさん:2006/09/13(水) 19:26:56
とか言いつつ>>1が気になってしかたがない>>46
そのレスに何の意味があるの?w
48デフォルトの名無しさん:2006/09/13(水) 21:57:17
きもい
49デフォルトの名無しさん:2006/09/13(水) 22:33:29
>一緒に勉強するお友達が欲しかったんでしょ?
50デフォルトの名無しさん:2006/09/13(水) 23:52:47
きもい
511:2006/09/14(木) 12:26:13
>>38
関数テーブルをクラスと分離することでメンバ変数の隠蔽もできるし、
コンストラクタで別メソッドを登録すれば派生クラスも簡単に
つくれるということね、なるほど。派生クラス側でメソッドのインターフェースを
追加したい場合はMap_Implementationをもう一個書けばいいのか。
でもこれ外注さんとか専門卒の一般PGとかメンテできなそうだね・・
521:2006/09/14(木) 12:32:35
ついて来れてない人にもマジレスしといてあげると、
listは1次元でmapは2次元です。keyとvalueが組になっていて
連想配列みたいに使うだけだけど、keyは任意の型で構わない。
俺の例でchar*にしたのは文字列じゃないと比較とかめんどくさいから。

で、順序を保持しているのがlinkedなんちゃらで、今回は順序を保持している
MapだからlinkMapにしてみた。linkedMapにしなかったのは、それならHashMapだって
HashedMapじゃねーのか?と思ったからで特に意味はない。JavaのLinkedHashMapは
順序を保持しつつ内部ではHash使ってget時の速度を向上させてる。俺のは
Hashによる検索速度向上がないからlinkMap。
53デフォルトの名無しさん:2006/09/14(木) 12:34:04
他人のメンテまで考えたら、
Cで自作でOOP近似のことが出来る俺様ライブラリって時点で
かなりNGじゃね?w
541:2006/09/14(木) 12:40:52
>>25
コレクション1個で終わりなわけねーだろ!。ちょっと便利な関数つくって
喜んでるわけじゃねーんだぞw

>>27
たぶんね、キミはね、"CPL"の"P"を突っ込まれてるんだと思うよ

>>34
あっちのスレにもstr->add()じゃなくてstrcatでいいじゃんという
人がいたけど、手続きを呼び出すのとオブジェクトにメッセージを投げて
処理してもらうのとでは、設計段階から大分違うよ。詳細設計通りに
作るだけのPGならかえって後者の方が面倒に感じるのかもしれない。
設計自体も手続き型で構造化設計の方が楽だと思ってる人は化石だから、
注意してね。規模が小さければそれでも十分で、生兵法のOOなんかより
よっぽど品質がいいのもいっぱいあるけど。
551:2006/09/14(木) 12:42:49
>>20
あなたみたいな人はアニオタも兼ねていらっしゃるんですか?

>>53
やっぱそう思う?w

56デフォルトの名無しさん:2006/09/14(木) 14:05:55
#include "myoops.h"

int main(int ac, char *av[])
{
struct window w;
struct button b;
createwindow(&w, "sample");
setsize(&w, 100, 50);
createbutton(&b, "test button", 20, 8);
appenditem(&w, 40, 10, &b);
showwindow(&w, 10, 20);
return 0;
}
57デフォルトの名無しさん:2006/09/14(木) 14:12:04
C++/MFC や Java の awt とどれほどの違いがあると言うのか
58デフォルトの名無しさん:2006/09/14(木) 14:12:42
>ついて来れてない人

マジレスすると、あきれてるんだと思うよ。
59デフォルトの名無しさん:2006/09/14(木) 14:29:18
CでOOっぽいプログラム書いているんで気になったスレなんだけど、
>>1がバカだったのか……。
60デフォルトの名無しさん:2006/09/14(木) 14:34:06
アホのみならず、英語にも弱そうだ
61デフォルトの名無しさん:2006/09/14(木) 14:38:11
頭が弱いんでしょ
62デフォルトの名無しさん:2006/09/14(木) 15:31:48
「予約」がReserveなのかReservationなのか迷って
よく動詞の原形を使う俺がいる
63デフォルトの名無しさん:2006/09/14(木) 16:07:31
未だに「登録」でRegistを使ってるソース見ると萎えるな。
64デフォルトの名無しさん:2006/09/14(木) 19:37:40
>>56
きれいな構造化プログラミングですね。
65デフォルトの名無しさん:2006/09/14(木) 22:54:57
データ抽象もできない言語だとOOPはどうしても不恰好だね。
66デフォルトの名無しさん:2006/09/14(木) 23:06:05
そのうちCでやるのは諦めるから、ほっとけば
67デフォルトの名無しさん:2006/09/15(金) 01:32:48
皆一度はやろうとして挫折した道なのかも知れないな……
どれだけ足掻いても、CはCなんだよ。
68デフォルトの名無しさん:2006/09/15(金) 01:36:44
CFって結構いいと思うんだけど。
69デフォルトの名無しさん:2006/09/15(金) 03:20:18
へー、Core Foundation って Windows でも使えるノカ。
サンプルコード探してみよ。
701:2006/09/15(金) 14:00:37
CoreFoundationはWindowsでも使えるのかもしれないけど、
OSXCompatibilityHeaders/*.hというヘッダファイル群が必要で
どっからとってくるのかググってもわからなかった。

Makefileにはfor Linuxとか for FreeBSDとかあるのでなんとか
なりそうだけど、開発環境がcygwin+Eclipse、本番がSolarisなので
とりあえずあきらめることにした。

でもいろいろ勉強になったよ。スマートポインタ実装するときは
CFを参考にしようと思った。
71デフォルトの名無しさん:2006/09/15(金) 14:05:35
CoreFoundationの実装

ttp://journal.mycom.co.jp/column/objc/
72デフォルトの名無しさん:2006/09/15(金) 16:51:52
もうみんなObjective-Cにすればいいのに
73デフォルトの名無しさん:2006/09/15(金) 17:07:38
そこでObjective-C++
74デフォルトの名無しさん:2006/09/16(土) 00:40:36
>>70
開発環境もソラリン入れれば良いんじゃないの。
普通の PC でも動くし、Eclipse も使えるよ。

>>72
ObjC は遅いのがネックじゃないかな。
上物は全部動的束縛になっちゃうから。
75デフォルトの名無しさん:2006/09/16(土) 06:03:13
結局C言語は汎用アセンブラだと悟ると、いろいろ見えてくるもんだ・・
Cで直接やろうとしないでさぁ;;
76デフォルトの名無しさん:2006/09/16(土) 07:05:57
そしてC++になった。
77デフォルトの名無しさん:2006/09/16(土) 07:41:07
>>1
メイヤー「オブジェクト指向入門」アスキー はいい本です
78デフォルトの名無しさん:2006/09/16(土) 14:18:07
クラス(構造体)のメンバにメソッドの関数ポインタを含めるとオブジェクトサイズがでかくなるよね。
サブクラスでC++っぽくオーバーライドを書けるメリットとどっちをとるべきか。
79デフォルトの名無しさん:2006/09/16(土) 14:31:03
唐突だけど、Pythonとかの実装って参考にならんのかな?
80デフォルトの名無しさん:2006/09/16(土) 18:04:48
>>78
C++で実装している、関数配列とか参考にしてみたら?
81デフォルトの名無しさん:2006/09/20(水) 00:44:00
>>80
メンバにメソッドのテーブルを持たせて、
メソッド呼び出しがobj->table->method()ってなるのかな。

obj->method(obj)のほうが使いやすい気がする。
objを2回書かなきゃならんけど。
82デフォルトの名無しさん:2006/09/20(水) 00:50:54
core foundation について載ってた。

http://journal.mycom.co.jp/column/objc/
831:2006/09/20(水) 01:38:59
ある程度出来てきたので、明日いくつかアップするかも。
で、やってて思ったのが
> objを2回書かなきゃならんけど。
これが意外と大変。どんなときに大変かというとこんな時。
obj->util(obj)->target(obj->util)->func(obj->util->target);

こうなるのを避けるために2行にしてもまだちょっとなあって感じ
target = obj->util(obj)->target(obj->util);
target->func(target);

>>82
@see >>71
841:2006/09/20(水) 03:55:13
あげてみたよ。結構疲れたよ。
誰か一緒にやりたいって人がいたらSouceForgeにでも登録するけど
ttp://x86-64.hp.infoseek.co.jp/
85デフォルトの名無しさん:2006/09/20(水) 04:41:50
obj->methods[0]
obj->methods[1]
86デフォルトの名無しさん:2006/09/20(水) 06:39:11
>>84
口だけ番長とはちょっと違うみたいだな。
String.hを開いて10秒の感想。
・名前を別のものにしたほうがいい。なぜなら、標準でstring.hがありまぎらわしいから。
・エラーの種別(エラーコードなど)は、どうやって戻すの?
・defineを使って、どんな関数が使えるのかを列挙したほうが見やすい。

*.cはコンパイルできるようになったら見るかも。
871:2006/09/20(水) 12:33:00
コンパイルはできるよ。
Allocator使ってメモリリークのデバッグ済みだよ
コンパイルしてみてくれる人がいるならsrc.zipの形でまとめた奴も置いた方が
いいかな。String.hはヘッダファイル名だけ別にすればいいってこと?
Stringっていう名前も変えた方がいい?

Windowsはファイルの大文字小文字を区別しないからなんだかなあとは
思っていたけど。
88デフォルトの名無しさん:2006/09/20(水) 15:42:31
>>87
できないよ。
ファイルが足りない。
89デフォルトの名無しさん:2006/09/20(水) 16:43:42
strcpyはやめれ。



90デフォルトの名無しさん:2006/09/20(水) 18:04:01
この手の妙な構造体って、作る分にはオナニックで楽しいんだけど
使う分には継承も隠蔽もできないしコンパイルエラーの表記がわけわかになるし
正直ゴミだと思うよ。
91デフォルトの名無しさん:2006/09/20(水) 20:34:16
クラスの一番目のメンバに親クラスの変数を持たせれば継承はできるが、キャストがめんどくさい。
そこで継承とメソッドのオーバーライドをキャストなしでする方法を考えた。

クラスを一つ定義する毎にマクロを3つ定義する。
・クラスや仮想関数の型定義をするマクロ。
・メンバを定義するマクロ。
・メンバを初期化するマクロ。

■Hoge.h
#define HOGE_DEFINE_CLASS(CLASS)  \
    typedef struct CLASS##_t CLASS;\
    typedef void (*CLASS##_destroy_t)(CLASS *self);\
    typedef void (*CLASS##_print_t)(CLASS *self);\

#define HOGE_DEFINE_MEMBER(CLASS) \
    int hoge;\
    CLASS##_destroy_t destroy;\
    CLASS##_print_t print;\

#define HOGE_INIT_METHOD(CLASS, HOGE) \
    self->hoge = HOGE;\
    self->destroy = (CLASS##_destroy_t) Hoge_destroy;\
    self->print = (CLASS##_print_t) Hoge_print;\

/* クラス定義 */
HOGE_DEFINE_CLASS(Hoge)
struct Hoge_t {
    HOGE_DEFINE_MEMBER(Hoge)
};
Hoge *Hoge_create(int hoge);
void Hoge_destroy(Hoge *self);
void Hoge_print(Hoge *self);
92デフォルトの名無しさん:2006/09/20(水) 20:35:30
■Hoge.c
#include "Hoge.h"
/* 初期化 */
static void Hoge_init(Hoge *self, int hoge)
{
    HOGE_INIT_METHOD(Hoge, hoge)
}
/* コンストラクタ */
Hoge *Hoge_create(int hoge)
{
    Hoge *self = (Hoge *) malloc(sizeof(Hoge));
    Hoge_init(self, hoge);
    return self;
}
/* デストラクタ */
void Hoge_destroy(Hoge *self)
{
    free(self);
}
void Hoge_print(Hoge *self)
{
    printf("%d\n", self->hoge);
}
93デフォルトの名無しさん:2006/09/20(水) 20:42:16
Hogeクラスを継承したPiyoクラス。printメソッドをオーバーライド。
■Piyo.h
#include "Hoge.h"
/* クラス定義 */
HOGE_DEFINE_CLASS(Piyo)
struct Piyo_t {
    HOGE_DEFINE_MEMBER(Piyo)
    /* 追加メンバ */
    int piyo;
};
Piyo *Piyo_create(int hoge, int piyo);
void Piyo_print(Piyo *self);

■Piyo.c
#include "Piyo.h"
static void Piyo_init(Piyo *self, int hoge, int piyo)
{
    HOGE_INIT_METHOD(Piyo, hoge)
    self->piyo = piyo;
    self->print = Piyo_print;
}
Piyo *Piyo_create(int hoge, int piyo)
{
    Piyo *self = (Piyo *) malloc(sizeof(Piyo));
    Piyo_init(self, hoge, piyo);
    return self;
}
void Piyo_print(Piyo *self)
{
    printf("%d, %d\n", self->hoge, self->piyo);
}
94デフォルトの名無しさん:2006/09/20(水) 20:46:59
■使うところ
Hoge *h = Hoge_create(1);
Piyo *p = Piyo_create(2, 3);

h->print(h);  /* 1 */
p->print(p);  /* 2, 3 */

h->destroy(h);
p->destroy(p);

Piyoクラスを継承したかったらさらに3つのマクロを定義する。
そうすれば何階層でも継承できる。
マクロ書くのがめんどくさいがスクリプトで自動生成できるようにがんばる。

このやり方どうでしょう?
95デフォルトの名無しさん:2006/09/20(水) 21:34:52
そんなメンテナンサビリティゼロのコードは却下。
961:2006/09/20(水) 22:48:55
一式アップした。テスト用main関数もつけた。
引数なしで起動するとtest.propertiesを読む。
$ ./a -f test2.properties
と打てばtest2.propertiesを読むよ。
http://x86-64.hp.infoseek.co.jp/src.zip

>>91
別にキャストしなくても中で委譲すればいんじゃね?
typedef struct __child {
  void (*func1)(struct __child *this);
  Super *super;
}Child;

// コンストラクタ
Child *Child_new(){
  Child *this = l_malloc(..);
  this->super = Super_new();
  this->func1 = this->super->func1;
}

試してないけど
97デフォルトの名無しさん:2006/09/20(水) 22:53:02
>>89
strcpyの前にstrlenでサイズチェックしてメモリ確保してるんだけど、
それでも駄目な場合って?引数にchar*を渡した直後に別スレッド
値を書き換えて、strlenとstrcpyの間に値が書き換えられたら
バッファオーバーフローをおこせるから?

そういう変な使い方も想定しておきたいな。サイズ調べてるんだし、memcpyにすればいい?
98デフォルトの名無しさん:2006/09/21(木) 00:31:30
Javaから離れろよ
99デフォルトの名無しさん:2006/09/21(木) 00:50:15
CFのクラスってそのままObjCオブジェクトとして扱えるのね。
10091:2006/09/21(木) 01:38:34
>>95
やっぱマクロのせいで読みづらいしバグが見つかりにくくなってしまうのがまずいですか。

>>96
委譲にする方法はいいアイデアと思ったけど、親クラスのデータメンバにアクセスするのが
大変になりますね。
現実的には何階層も継承したりしないけど、もしした場合、
this->super->super->super->...->super->data
って書かなきゃいけなくなる。
一応自分のメンバなんだから、すっきりthis->dataか、せめて(Super *)this->dataって書けたらなあ。
1011:2006/09/21(木) 02:20:10
つーかデータメンバ(メンバ変数の事だよね?)にはアクセスしちゃいかんだろ
102デフォルトの名無しさん:2006/09/21(木) 02:46:51
こういう感じじゃいけないの?

typedef struct
{
Class_init_type init;
Class_finish_type finish;
Class_new_type new_;
Class_delete_type delete_;
}Class_function;

test(){
Class* c;
Class_function fn;
fn = get_Class_function();//get_SubClass_function();
c = fn.new_();
fn.init(c);
fn.finish(c);
fn.delete_(c);
}
103デフォルトの名無しさん:2006/09/21(木) 03:41:08
表記を考えるという事は
結局はコンパイラやスクリプトで言語を作ったほうが速いんだよ。
その意気込みをもうちょっとだけ進めて、
そのエネルギーをD言語とかまだ進化中のフィールドで生かせ!
104デフォルトの名無しさん:2006/09/21(木) 03:43:28
とりあえず、私のスレを置いておきますね
http://pc8.2ch.net/test/read.cgi/tech/1156692664/
105デフォルトの名無しさん:2006/09/21(木) 04:15:30
>>1
そんなあなたにはObjective-Cをすすめる。
Objevtive-Cは、おもいっきりCでOOを実現しているといっていい言語だし、Cと完全互換性があるから、Cのソースをそのまま使えるよ。
106デフォルトの名無しさん:2006/09/21(木) 04:19:23
>>105
ちょおまwwww
C++(C with objects)でいいじゃないか
107デフォルトの名無しさん:2006/09/21(木) 04:21:57
C++ は C との完全互換性がありません
108デフォルトの名無しさん:2006/09/21(木) 05:17:10
C++は、Cをそっくり真似ているだけで
Cとの互換を維持するつもりで作ったんじゃないからねぇ
1091:2006/09/21(木) 05:20:15
誤解があるようなので言っておきますが、趣味でプログラム書くならJavaかC#にします。
別にOOを究めるなにかを求めているわけではなくて、仕事上Cのプログラムを
書かざるを得なくなったけど(C++不可)、なんとかラクをしたいなー、というのが出発点です。
全関数がグローバルスコープなままだと疲れるので、他のOO言語っぽくやりたいのです。
110デフォルトの名無しさん:2006/09/21(木) 05:53:42
POC(Portable Object Compiler) みたいなトランスレータを使えばオケ。
って話題がループしてるな。

http://users.pandora.be/stes/compiler.html
111デフォルトの名無しさん:2006/09/21(木) 09:33:23
glibみたいな既存のものは見たのか?
http://www.gnome.gr.jp/docs/glib/glib-data-types.html
112デフォルトの名無しさん:2006/09/21(木) 10:22:15
あれもこれも、一体何をやりたいわけなの?
仕様をはっきりさせないから、意味わかんないじゃんかよー
113デフォルトの名無しさん:2006/09/21(木) 12:21:05
Cのコードを出力するC++コンパイラとか探せばあるだろ。
114デフォルトの名無しさん:2006/09/21(木) 15:58:31
>>108
少なくとも、作った当初は上位互換性を求めていた。
だからこそあんな糞汚(ry
115デフォルトの名無しさん:2006/09/21(木) 15:59:53
>>112
>>1 は、手段がいつのまにか目的になってしまうタイプ。
116デフォルトの名無しさん:2006/09/21(木) 17:24:42
すまん、>>106の意図が全く分からない。
117デフォルトの名無しさん:2006/09/21(木) 17:42:45
106はObjective-Cなんてマイナーなもの薦めるなと言いたいのではないかと思う。
118デフォルトの名無しさん:2006/09/21(木) 18:26:25
なんだ、たいしたことないじゃん。
期待して損したよ。
119デフォルトの名無しさん:2006/09/21(木) 21:11:24
1. 継承時にOOP言語のように差分のみ記述するだけでよいようにしたい。
2. コンストラクタ以外の全てのメソッドの呼び出しは、obj->method(obj)の形で統一したい。

1を満たすと、親クラスの仮想関数呼び出し時にキャストが必要になる。(オーバーライドの場合は不要)
Super_method((Super *)obj)または((Super *)obj)->method((Super *)obj)と書くしかない。

2を満たすと、親クラスが持ってるにもかかわらず
(型は違うが)同じメソッドのポインタを子クラスのメンバにも持つ必要がある。
その分無駄なメモリを使うことになるし、親の全メソッドのポインタをまた書いて初期化するのがめんどくさい。

この2つを満たす方法はないもんだろうか?
120デフォルトの名無しさん:2006/09/21(木) 21:14:29
vtblの仕組み知らないの?
121デフォルトの名無しさん:2006/09/21(木) 21:47:27
>>120
子クラスのテーブルに親クラスのメソッドも全部書かなきゃならんから
差分書くだけでOK、にならない。
122デフォルトの名無しさん:2006/09/21(木) 21:49:36
話にならん
123デフォルトの名無しさん:2006/09/21(木) 21:56:10
継承なんかできなくてもいいじゃん。
124デフォルトの名無しさん:2006/09/21(木) 22:02:18
クラスをstructで書こうとするからはまる。
クラスはclassクラスのインスタンスにしろ。
125デフォルトの名無しさん:2006/09/21(木) 22:23:19
>>119
最速で動くように実装して、あとはoptionにしてよ。
無駄に遅いのはライブラリとして役に立たない。
126デフォルトの名無しさん:2006/09/21(木) 23:18:00
この本に載ってたマクロを使ってテンプレートを実現するやり方
http://www.amazon.co.jp/gp/product/4789833399
どんな型でもいけるが、バグがどこにあるかわからなくなるので
マクロ化する前にしっかりデバッグしろと書いてあった
#define InterfaceStack(NANE,TYPE,MAX) \
  typedef struct {\
    int sp;\
    TYPE buf[MAX];\
  }NAME;\
  void init_##NAME(NAME *self);\
  void push_##NAME(NAME *self,TYPE data);\
  TYPE pop_##NAME(NAME *self);\

#define ImplementStack(NAME,TYPE)\
  void init_##NAME(NAME *self){ 略 }\
  void push_##NAME(NAME *self,TYPE data){ 略 }\
  TYPE pop_##NAME(NAME *self){ 略 }\
127デフォルトの名無しさん:2006/09/21(木) 23:43:06
C++の設計と進化にも同じようなことが書いてあって、
初期のC++にはマクロでクラステンプレートもどきを提供する<generic.h>があったそうな。
128デフォルトの名無しさん:2006/09/22(金) 01:13:59
C++でマクロでやってたとは知らんかった。ならC言語版STLもできるな
129デフォルトの名無しさん:2006/09/22(金) 01:52:49
>>126
その手のは何度か作った事あるな。
130デフォルトの名無しさん:2006/09/22(金) 02:43:43
>>108
> Cとの互換を維持するつもりで作ったんじゃないからねぇ
ダウト
131デフォルトの名無しさん:2006/09/22(金) 02:55:43
上位互換性はかなり腐心してたはずだな。
わずかながら維持できなかった所もあるが。
132デフォルトの名無しさん:2006/09/22(金) 03:02:37
非互換が大きくなったはC99がでてからだけど、
これはあとだしジャンケンみたいなものだからいたしかたなし。
133デフォルトの名無しさん:2006/09/22(金) 05:42:55
>>130
維持するつもりなら、CとC++との互換問題はまったく起きないはずだけど、どのへんが?
134デフォルトの名無しさん:2006/09/22(金) 08:04:58
またもD&Eからだが、
C++標準化の際にCとの100%の互換性は求めないこということに決まったとある。
なんでも型安全などの都合らしい。
135デフォルトの名無しさん:2006/09/22(金) 08:06:59
継承するのに差分だけ書きたい?
一体どこの話をしてるのだろう。structの話か?
136デフォルトの名無しさん:2006/09/22(金) 11:26:07
Cでooは無理。ソースが汚すぎる。
gtkというライブラリを見てみなさい。
C++やjavaで言うメンバ関数を使うためには、
わざわざキャストのマクロを定義して、何のクラスなのかを明示する必要がある。
そこまでしてCで書く利点はなど何もない。
137デフォルトの名無しさん:2006/09/22(金) 13:32:14
>>136
お前、Objective-Cを知らないな
138デフォルトの名無しさん:2006/09/22(金) 15:12:42
>>134
100% の互換性は求めてないけど、
最小限の変更で何とかなるようにはしたんじゃない?
139デフォルトの名無しさん:2006/09/22(金) 15:53:05
まずはスタック作ってみれば?

stack->push(stack, value);
(*stack).push(stack, value);
stack[0].push(stack, value);

stack[0].dispose(stack);
140デフォルトの名無しさん:2006/09/22(金) 16:04:17
それOOと何の関係が?
141デフォルトの名無しさん:2006/09/22(金) 16:30:40
この程度かぁ
142デフォルトの名無しさん:2006/09/22(金) 19:40:16
おまいら、ここが「公開オナニースレ」なのは最初から判っていたはずだろ?
143デフォルトの名無しさん:2006/09/22(金) 23:20:16
Message(obj, say, "unko", "うんこ");

obj->class->methods->say(obj, "unko", "うんこ");
の様に展開出来るマクロはないの?
C99の可変長引数を受け取れるマクロってstdarg使わないといけないんだっけ?
144デフォルトの名無しさん:2006/09/23(土) 00:15:53
>>126のやり方でlistを実装した。
インターフェイスはSTLにならって。popは値を返すようにしたけど。
こんな感じで使える。 アプリ毎にlistを実装しなくて済むから便利だ。
IntList *ls = IntList_create();
IntListIterator pos;
ls->push_back(ls, 1);
ls->push_back(ls, 2);
ls->push_back(ls, 3);
for (pos = ls->begin(ls); pos != ls->end(ls); pos = pos->next) {
    int i = ls->get(pos);
    if (i == 2) ls->insert(ls, pos, 4);
}
while (!ls->empty(ls)) {
    int i = ls->pop_front(ls);
    printf("%d ", i); /* 1 4 2 3 を出力 */
}
ls->destroy(ls);
145デフォルトの名無しさん:2006/09/23(土) 01:36:06
>>144
初期化前に初期化関数を呼び出せない罠。

IntArray ar;
ar.init(&ar);//アボンヌ
146デフォルトの名無しさん:2006/09/23(土) 01:40:19
>>146
create()の中でmalloc()してメンバを初期化してる。C++のnewみたいなもん。
だからdeleteに相当するdestroy()で解放が必要。
1471:2006/09/23(土) 02:56:55
HttpClientをKeepAlive対応にしたいんだけど、socketが生きてるかどうかって
どうやって判断したらいいの?manみたんだけど、一旦sendしてEPIPE拾うしか
ないのかな?このソースだとfprintfで0が返ってきたらerrnoをチェックしろって
事かなあ。シグナルが発生しないようにMSG_NOSIGNALをセットするのって
もしかしてfopenとfprintfの組み合わせじゃ出来ない?
148デフォルトの名無しさん:2006/09/23(土) 03:20:57
keepaliveの仕組みを勘違いしていませんか?
1491:2006/09/23(土) 03:38:25
今はHttpClientにはnew()とget()しかない。この内get()をconnect()とget()に分ける。
get()では今fgets==NULLになるまで読み込んでるけど、KeepAliveの終端文字"0\r\n\r\n"(?要調査)
が来たら返すように変更する。connect()は最初の1回だけで、あとはget()だけを
繰り返し呼ぶんだけど、KeepAliveのTimeoutで相手先に接続を切られている場合が
あるから、その場合は再接続してあげないといけない。

だからsocketが生きているかチェックしたいんだけど、なにか間違ってる?
150デフォルトの名無しさん:2006/09/23(土) 08:53:19
しかし1へ注元したやつは、こんな事を望んでCで書くように条件つけたのだろうか・・・
151デフォルトの名無しさん:2006/09/23(土) 10:47:35
>注元
???
#何とどう間違えたのだろう……
152デフォルトの名無しさん:2006/09/23(土) 11:15:57
注文
153デフォルトの名無しさん:2006/09/23(土) 11:21:49
それをどう間違えたら注元になるのか知りたい。
154デフォルトの名無しさん:2006/09/23(土) 11:28:28
変なこと知りたいんですね
155デフォルトの名無しさん:2006/09/23(土) 13:59:21
思ったよりもこのスレ結構のびるなww
1561:2006/09/23(土) 17:25:08
発注元と悩んでたらこうなっちゃったんだろう
157デフォルトの名無しさん:2006/09/25(月) 23:19:11
誰か、getter と setter の雛型書いてくだちぃ。
いや、ね、JavaのPureObjectをC++風にするとどうなるのか知りたくてさ。
158sage:2006/09/25(月) 23:51:16
そんなあなたにIUnknown。
実装したクラスもいぱーいあるよ
159デフォルトの名無しさん:2006/09/29(金) 01:28:53
>>91の継承の仕方そんなに保守性悪いと思わないんだけどな
160デフォルトの名無しさん:2006/09/29(金) 02:02:38
やっぱりC++でいいや、と思い始めた今日のこの頃。
161デフォルトの名無しさん:2006/10/01(日) 00:14:18
C/C++でコンテナクラスを作る場合、コンテナに登録されているオブジェクトを
破棄するのって、普通はコンテナクラスの外部でやるものなのだろうか。
162デフォルトの名無しさん:2006/10/01(日) 00:15:55
>>161
containerはfactoryじゃないからなぁ…
積荷を勝手に食われちゃ商売上がったりだよなぁ…


とデザパタを全く知らない俺が言ってみるテスツ
163デフォルトの名無しさん:2006/10/01(日) 01:15:37
>>161
STLがどうなっているか見てみて、それを参考にしたらどう。
164デフォルトの名無しさん
>>161
smart pointer入れたらどうなるか