0

私は現在、C で OOP 手法を使用しており、次のように、構造体内に親クラスのインスタンスを持つ子クラスの既知のイディオムを使用しました。

struct parent{
    void (*doSomething)(struct parent *parent);
};

struct child{
    struct parent base;
    int (*doSomethingCooler)(struct child *child);
};

現在、私のメソッドには、それらが属するクラスのプレフィックスが付けられています。

void parent_doSomething(struct parent *parent);
int child_doSomethingCooler(struct child *child);

過負荷で、私は持っています

void child_doSomethingCool(struct parent *parent);

子コンストラクター関数でparent->doSomethingに設定しました。

とにかく、子インスタンスがあり、親メソッドを呼び出したいときに問題が発生します。すぐに、インスタンス ポインターを親クラスの型にキャスト (C の dynamic_cast のようなもの) する必要があり、これによりコードが急速に汚染されます。

2 番目のアイデアは、すべてのメソッドが void * "this" パラメーターを受け取るように定義し、それらを内部的に適切なクラスにキャストすることでした。これにより、クライアント コードからの使用が簡素化されますが、無効な参照を渡す、または間違った型の参照を渡すなどの厄介なバグにコードがさらされます。

各実装の長所と短所は何ですか?

4

2 に答える 2

3

C11 の新しいタイプ ジェネリック機能を使用すると、親パーツに均一にアクセスできます。

#define getParent(X)        \
_Generic((X),               \
    parent*: (X),           \
    child*: (&(X)->base)))

そして、関数名をマクロでオーバーロードできます

#define doSomething(X) doSomething(getParent(X))

これらの例からわかるように、これは などのポインターを介して「メソッド」を呼び出す OO 表記ではうまく機能しませんp->doSomething()が、これは出発点になる可能性があります。

于 2012-08-27T19:18:43.200 に答える
0

私が考えた 1 つの解決策は、各クラスに MAGIC WORD を追加し、実行時にそれらをチェックすることでした。この「機能」がリリースビルドでコンパイルされないようにすることで、メモリの浪費と処理のオーバーヘッドを回避できました。

このようにして、これらのクラスを使用してクライアント コードを簡素化し、悪いコードから身を守ることもできます。

于 2012-08-27T18:32:01.503 に答える