[今さら]C言語でクラスライブラリを作る[Cかよ]
C言語でOO的に使えるクラスライブラリを作ります。
OOに慣れてしまって今さら手続き型言語で設計できないorやりたくないのに、
Cで仕事しないといけない、そんなときにちょっと楽ができたらいいなと。
「Cで無理矢理OOすんな」とか言わないでね。
Cで無理矢理OOすんな
#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_
上のは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クラスがあります。
ソースアップするところは別に考えます。
インターフェースですが、デストラクタコールがmap2->destructor(map2);
なのがおかしいよね。
コンストラクタとデストラクタはこんな風にした方がいいかなと
思ってるんだけどどうだろう
LinkMap map = new_LinkMap();
delete_LinkMap(map);
あとc++でいうthisポインタを渡すのに、いちいち自信のインスタンスを
引数で渡しているところが冗長で嫌なんだけど、Cでやる以上
仕方ないのかなあ
6 :
デフォルトの名無しさん:2006/09/13(水) 10:15:50
C++->Cへのいいpreprocessorを作れば?
7 :
1:2006/09/13(水) 10:24:10
それだ!
言い出しっぺがつくるの法則でお願いします。
つーかありそうだよね。
>>7 その調子で、お前はノリだけで生きてきたんだろうな。
そんなんじゃ、どんどんと出来る奴らに追い抜かれるだろうけど、それでいいのか?
ぐだぐだ言ってないで、暇なら作ろう。
ちょっと昼休みした後、また再開する。
glibみたく、外部インターフェースは
LinkMap_new
LinkMap_put
LinkMap_get
LinkMap_destroy
でいいじゃん。
明示的にthisポインタ渡すのは面倒すぎ。
11 :
1: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ポインタを渡さないで複数の
インスタンスを切り分ける別の方法をとるってこと?
インスタンスを特定するためのキーはなにか渡さないと
いけないわけでしょ?
>>11 書き方変だったな。
メソッドを参照するのと引数の二回、同じのを書くのが面倒って事で。
俺的お勧めは linkMap_get(map, "key"); の方かな。
struct __linkMap;
typedef struct __linkMap linkMap_t;
linkMap_t * LinkMap_new (void);
void LinkMap_destroy (linkMap_t *);
のように、構造体の中身を一切見せない、とかもできるし。
・linkMapってナニ?
・それOOと何の関係が?
15 :
デフォルトの名無しさん:2006/09/13(水) 12:58:46
C++からCへのトランスレータ使えば?
OO ←これって何かの目?ですか?
Object Oppai の略ですか?
分かりません><;
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で仕事することはもうほとんどないし、自作ライブラリよりもちゃんとメンテナの
いるライブラリを利用する方が効率いいからなあと思ったんだけど、
ちょっと別スレ建ててみますわ。まあスレが伸びなきゃ伸びないで終了ということで
linkMapってJavaの方言か何か?
JavaにはLinkedHashMapというのがあるが>1のlinkMapとの関連は不明。
>>3を見る限り、単なるlink-list(linked-list)にしか見えないのだが・・・
24 :
デフォルトの名無しさん:2006/09/13(水) 13:38:38
スレまで立てて、本当はヒマなんじゃねーの
こんなことするなら、自分で作って終わりでしょ
ていうか、そのスキルもなさそうだけどな
ケケケ
つーか、そのlinkMapとやらは完成してるんだろ?
何がやりたいんだろう?
「クラスライブラリ」ってどんなの想定してるんだろう。
27 :
デフォルトの名無しさん:2006/09/13(水) 13:58:44
「マクロテンプレートのコンテナとアルゴリズム」って何?
俺用語じゃ伝わらないよ。
>>1 そんなくだらんこと考える暇があったら、checkでも使ってUnit Test書け
>>20 >ここはおまえの来るところじゃねーんだよ!
いや、このスレで隔離できるものならそうして欲しい。
31 :
27: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();
}
"CPL"って何だよ?
あー、イライラするwww
33 :
27:2006/09/13(水) 15:17:48
cpl_vector_int_push_back(100);
修正w
struct {
int count;
int* array;
}
でいいじゃん。
隔離成功。
>>4 別にメンバ関数のようなシンタックスにする必要はない
それはオブジェクト指向とは(本当は)関係がない
問題はデストラクタの自動呼出しに集中すると思う
ポリモーフィズムを使いたいんでしょ
(データ構造と手続きの)カプセル化とポリモルフィズムさえ出来れば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
モノポリーでもやってろカス
「ポリ」しかおうてへんやんか!
CoreFoundation使ってろカス
42 :
1:2006/09/13(水) 17:54:28
これもOOと関係ないけど、デストラクタの自動呼び出しもMapの実装の時に気になってた。
keyはchar*で受け取ってるからコピーしてMapのデストラクタで解放するけど、
valueの方はどうしたらいいんだろうって。勝手に解放しちゃまずいし、かといって
解放しないと同一keyで別のオブジェクトが登録されたときにメモリリークしてもまずいし。
スマートポインタ実装しようにも、ジェネリックがないからメンバメソッド呼出の度に
キャストしなきゃいけないし。あ、でもこれはインスタンスに対してメソッド呼び出し
というシンタックスにこだわらなきゃいけるか。
CoreFoundationはいいかも。
>>41はカスとか言ってるけど一緒に勉強する
お友達が欲しかったんでしょ?もうちょっと見てみる。
Java莫迦みたいだな
44 :
1:2006/09/13(水) 18:33:00
45 :
1:2006/09/13(水) 18:34:30
あ、ごめんtar.gzあったわ
隔離完了。
とか言いつつ
>>1が気になってしかたがない
>>46。
そのレスに何の意味があるの?w
きもい
>一緒に勉強するお友達が欲しかったんでしょ?
きもい
51 :
1:2006/09/14(木) 12:26:13
>>38 関数テーブルをクラスと分離することでメンバ変数の隠蔽もできるし、
コンストラクタで別メソッドを登録すれば派生クラスも簡単に
つくれるということね、なるほど。派生クラス側でメソッドのインターフェースを
追加したい場合はMap_Implementationをもう一個書けばいいのか。
でもこれ外注さんとか専門卒の一般PGとかメンテできなそうだね・・
52 :
1: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。
他人のメンテまで考えたら、
Cで自作でOOP近似のことが出来る俺様ライブラリって時点で
かなりNGじゃね?w
54 :
1:2006/09/14(木) 12:40:52
>>25 コレクション1個で終わりなわけねーだろ!。ちょっと便利な関数つくって
喜んでるわけじゃねーんだぞw
>>27 たぶんね、キミはね、"CPL"の"P"を突っ込まれてるんだと思うよ
>>34 あっちのスレにもstr->add()じゃなくてstrcatでいいじゃんという
人がいたけど、手続きを呼び出すのとオブジェクトにメッセージを投げて
処理してもらうのとでは、設計段階から大分違うよ。詳細設計通りに
作るだけのPGならかえって後者の方が面倒に感じるのかもしれない。
設計自体も手続き型で構造化設計の方が楽だと思ってる人は化石だから、
注意してね。規模が小さければそれでも十分で、生兵法のOOなんかより
よっぽど品質がいいのもいっぱいあるけど。
55 :
1:2006/09/14(木) 12:42:49
>>20 あなたみたいな人はアニオタも兼ねていらっしゃるんですか?
>>53 やっぱそう思う?w
#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;
}
C++/MFC や Java の awt とどれほどの違いがあると言うのか
>ついて来れてない人
マジレスすると、あきれてるんだと思うよ。
CでOOっぽいプログラム書いているんで気になったスレなんだけど、
>>1がバカだったのか……。
アホのみならず、英語にも弱そうだ
頭が弱いんでしょ
「予約」がReserveなのかReservationなのか迷って
よく動詞の原形を使う俺がいる
未だに「登録」でRegistを使ってるソース見ると萎えるな。
データ抽象もできない言語だとOOPはどうしても不恰好だね。
66 :
デフォルトの名無しさん:2006/09/14(木) 23:06:05
そのうちCでやるのは諦めるから、ほっとけば
皆一度はやろうとして挫折した道なのかも知れないな……
どれだけ足掻いても、CはCなんだよ。
CFって結構いいと思うんだけど。
へー、Core Foundation って Windows でも使えるノカ。
サンプルコード探してみよ。
70 :
1:2006/09/15(金) 14:00:37
CoreFoundationはWindowsでも使えるのかもしれないけど、
OSXCompatibilityHeaders/*.hというヘッダファイル群が必要で
どっからとってくるのかググってもわからなかった。
Makefileにはfor Linuxとか for FreeBSDとかあるのでなんとか
なりそうだけど、開発環境がcygwin+Eclipse、本番がSolarisなので
とりあえずあきらめることにした。
でもいろいろ勉強になったよ。スマートポインタ実装するときは
CFを参考にしようと思った。
もうみんなObjective-Cにすればいいのに
そこでObjective-C++
>>70 開発環境もソラリン入れれば良いんじゃないの。
普通の PC でも動くし、Eclipse も使えるよ。
>>72 ObjC は遅いのがネックじゃないかな。
上物は全部動的束縛になっちゃうから。
75 :
デフォルトの名無しさん:2006/09/16(土) 06:03:13
結局C言語は汎用アセンブラだと悟ると、いろいろ見えてくるもんだ・・
Cで直接やろうとしないでさぁ;;
そしてC++になった。
>>1 メイヤー「オブジェクト指向入門」アスキー はいい本です
クラス(構造体)のメンバにメソッドの関数ポインタを含めるとオブジェクトサイズがでかくなるよね。
サブクラスでC++っぽくオーバーライドを書けるメリットとどっちをとるべきか。
唐突だけど、Pythonとかの実装って参考にならんのかな?
>>78 C++で実装している、関数配列とか参考にしてみたら?
>>80 メンバにメソッドのテーブルを持たせて、
メソッド呼び出しがobj->table->method()ってなるのかな。
obj->method(obj)のほうが使いやすい気がする。
objを2回書かなきゃならんけど。
83 :
1: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
84 :
1:2006/09/20(水) 03:55:13
obj->methods[0]
obj->methods[1]
>>84 口だけ番長とはちょっと違うみたいだな。
String.hを開いて10秒の感想。
・名前を別のものにしたほうがいい。なぜなら、標準でstring.hがありまぎらわしいから。
・エラーの種別(エラーコードなど)は、どうやって戻すの?
・defineを使って、どんな関数が使えるのかを列挙したほうが見やすい。
*.cはコンパイルできるようになったら見るかも。
87 :
1:2006/09/20(水) 12:33:00
コンパイルはできるよ。
Allocator使ってメモリリークのデバッグ済みだよ
コンパイルしてみてくれる人がいるならsrc.zipの形でまとめた奴も置いた方が
いいかな。String.hはヘッダファイル名だけ別にすればいいってこと?
Stringっていう名前も変えた方がいい?
Windowsはファイルの大文字小文字を区別しないからなんだかなあとは
思っていたけど。
strcpyはやめれ。
この手の妙な構造体って、作る分にはオナニックで楽しいんだけど
使う分には継承も隠蔽もできないしコンパイルエラーの表記がわけわかになるし
正直ゴミだと思うよ。
クラスの一番目のメンバに親クラスの変数を持たせれば継承はできるが、キャストがめんどくさい。
そこで継承とメソッドのオーバーライドをキャストなしでする方法を考えた。
クラスを一つ定義する毎にマクロを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);
■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);
}
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);
}
■使うところ
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つのマクロを定義する。
そうすれば何階層でも継承できる。
マクロ書くのがめんどくさいがスクリプトで自動生成できるようにがんばる。
このやり方どうでしょう?
そんなメンテナンサビリティゼロのコードは却下。
96 :
1: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;
}
試してないけど
>>89 strcpyの前にstrlenでサイズチェックしてメモリ確保してるんだけど、
それでも駄目な場合って?引数にchar*を渡した直後に別スレッド
値を書き換えて、strlenとstrcpyの間に値が書き換えられたら
バッファオーバーフローをおこせるから?
そういう変な使い方も想定しておきたいな。サイズ調べてるんだし、memcpyにすればいい?
Javaから離れろよ
CFのクラスってそのままObjCオブジェクトとして扱えるのね。
100 :
91:2006/09/21(木) 01:38:34
>>95 やっぱマクロのせいで読みづらいしバグが見つかりにくくなってしまうのがまずいですか。
>>96 委譲にする方法はいいアイデアと思ったけど、親クラスのデータメンバにアクセスするのが
大変になりますね。
現実的には何階層も継承したりしないけど、もしした場合、
this->super->super->super->...->super->data
って書かなきゃいけなくなる。
一応自分のメンバなんだから、すっきりthis->dataか、せめて(Super *)this->dataって書けたらなあ。
101 :
1: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言語とかまだ進化中のフィールドで生かせ!
105 :
デフォルトの名無しさん:2006/09/21(木) 04:15:30
>>1 そんなあなたにはObjective-Cをすすめる。
Objevtive-Cは、おもいっきりCでOOを実現しているといっていい言語だし、Cと完全互換性があるから、Cのソースをそのまま使えるよ。
>>105 ちょおまwwww
C++(C with objects)でいいじゃないか
C++ は C との完全互換性がありません
C++は、Cをそっくり真似ているだけで
Cとの互換を維持するつもりで作ったんじゃないからねぇ
109 :
1:2006/09/21(木) 05:20:15
誤解があるようなので言っておきますが、趣味でプログラム書くならJavaかC#にします。
別にOOを究めるなにかを求めているわけではなくて、仕事上Cのプログラムを
書かざるを得なくなったけど(C++不可)、なんとかラクをしたいなー、というのが出発点です。
全関数がグローバルスコープなままだと疲れるので、他のOO言語っぽくやりたいのです。
112 :
デフォルトの名無しさん:2006/09/21(木) 10:22:15
あれもこれも、一体何をやりたいわけなの?
仕様をはっきりさせないから、意味わかんないじゃんかよー
Cのコードを出力するC++コンパイラとか探せばあるだろ。
>>108 少なくとも、作った当初は上位互換性を求めていた。
だからこそあんな糞汚(ry
106はObjective-Cなんてマイナーなもの薦めるなと言いたいのではないかと思う。
118 :
デフォルトの名無しさん:2006/09/21(木) 18:26:25
なんだ、たいしたことないじゃん。
期待して損したよ。
1. 継承時にOOP言語のように差分のみ記述するだけでよいようにしたい。
2. コンストラクタ以外の全てのメソッドの呼び出しは、obj->method(obj)の形で統一したい。
1を満たすと、親クラスの仮想関数呼び出し時にキャストが必要になる。(オーバーライドの場合は不要)
Super_method((Super *)obj)または((Super *)obj)->method((Super *)obj)と書くしかない。
2を満たすと、親クラスが持ってるにもかかわらず
(型は違うが)同じメソッドのポインタを子クラスのメンバにも持つ必要がある。
その分無駄なメモリを使うことになるし、親の全メソッドのポインタをまた書いて初期化するのがめんどくさい。
この2つを満たす方法はないもんだろうか?
vtblの仕組み知らないの?
>>120 子クラスのテーブルに親クラスのメソッドも全部書かなきゃならんから
差分書くだけでOK、にならない。
話にならん
継承なんかできなくてもいいじゃん。
クラスをstructで書こうとするからはまる。
クラスはclassクラスのインスタンスにしろ。
125 :
デフォルトの名無しさん:2006/09/21(木) 22:23:19
>>119 最速で動くように実装して、あとはoptionにしてよ。
無駄に遅いのはライブラリとして役に立たない。
この本に載ってたマクロを使ってテンプレートを実現するやり方
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){ 略 }\
C++の設計と進化にも同じようなことが書いてあって、
初期のC++にはマクロでクラステンプレートもどきを提供する<generic.h>があったそうな。
C++でマクロでやってたとは知らんかった。ならC言語版STLもできるな
>>108 > Cとの互換を維持するつもりで作ったんじゃないからねぇ
ダウト
上位互換性はかなり腐心してたはずだな。
わずかながら維持できなかった所もあるが。
非互換が大きくなったはC99がでてからだけど、
これはあとだしジャンケンみたいなものだからいたしかたなし。
>>130 維持するつもりなら、CとC++との互換問題はまったく起きないはずだけど、どのへんが?
またもD&Eからだが、
C++標準化の際にCとの100%の互換性は求めないこということに決まったとある。
なんでも型安全などの都合らしい。
継承するのに差分だけ書きたい?
一体どこの話をしてるのだろう。structの話か?
Cでooは無理。ソースが汚すぎる。
gtkというライブラリを見てみなさい。
C++やjavaで言うメンバ関数を使うためには、
わざわざキャストのマクロを定義して、何のクラスなのかを明示する必要がある。
そこまでしてCで書く利点はなど何もない。
>>136 お前、Objective-Cを知らないな
>>134 100% の互換性は求めてないけど、
最小限の変更で何とかなるようにはしたんじゃない?
まずはスタック作ってみれば?
stack->push(stack, value);
(*stack).push(stack, value);
stack[0].push(stack, value);
stack[0].dispose(stack);
それOOと何の関係が?
この程度かぁ
おまいら、ここが「公開オナニースレ」なのは最初から判っていたはずだろ?
Message(obj, say, "unko", "うんこ");
を
obj->class->methods->say(obj, "unko", "うんこ");
の様に展開出来るマクロはないの?
C99の可変長引数を受け取れるマクロってstdarg使わないといけないんだっけ?
>>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 create()の中でmalloc()してメンバを初期化してる。C++のnewみたいなもん。
だからdeleteに相当するdestroy()で解放が必要。
147 :
1: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の仕組みを勘違いしていませんか?
149 :
1: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で書くように条件つけたのだろうか・・・
>注元
???
#何とどう間違えたのだろう……
注文
それをどう間違えたら注元になるのか知りたい。
変なこと知りたいんですね
思ったよりもこのスレ結構のびるなww
156 :
1:2006/09/23(土) 17:25:08
発注元と悩んでたらこうなっちゃったんだろう
157 :
デフォルトの名無しさん:2006/09/25(月) 23:19:11
誰か、getter と setter の雛型書いてくだちぃ。
いや、ね、JavaのPureObjectをC++風にするとどうなるのか知りたくてさ。
そんなあなたにIUnknown。
実装したクラスもいぱーいあるよ
>>91の継承の仕方そんなに保守性悪いと思わないんだけどな
やっぱりC++でいいや、と思い始めた今日のこの頃。
C/C++でコンテナクラスを作る場合、コンテナに登録されているオブジェクトを
破棄するのって、普通はコンテナクラスの外部でやるものなのだろうか。
>>161 containerはfactoryじゃないからなぁ…
積荷を勝手に食われちゃ商売上がったりだよなぁ…
とデザパタを全く知らない俺が言ってみるテスツ
>>161 STLがどうなっているか見てみて、それを参考にしたらどう。
>>161 smart pointer入れたらどうなるか