4

C はオブジェクト指向ではないため、メソッドに最も近い方法は、構造体で関数ポインターを使用することです。これは単なる思考練習ですが、次のことは可能ですか。

list.add(void* data)

リスト自体をパラメータとして渡さずに

そんなこと知ってる:

list.add(list_t* list, void* data)

実装は簡単ですが、C のどの部分を使用しても、この方法でメソッドをシミュレートする方法はありますか?

答えが「いいえ」である可能性があることは認識していますが、できれば説明してください! ありがとう。

4

4 に答える 4

6

これは、可変引数マクロ(C99)を使用して取得した最も美しい構文です。

#define call(obj, method, ...) ((obj).method(&(obj), __VA_ARGS__))

使用法 (ideone をクリック) :

struct class {
    int a;
    int (*method)(struct class* this, int b, int c);
};

int code(struct class* this, int b, int c) {
    return this->a*b+c;
}

struct class constructor(int a) {
    struct class result = {a, code};
    return result;
}

#define call(obj, method, ...) ((obj).method(&(obj), __VA_ARGS__))

#include <stdio.h>
int main() {
    struct class obj = constructor(10);
    int result = call(obj, method, 2, 3);
    printf("%d\n", result);
    return 0;
}
于 2013-06-27T08:39:33.103 に答える
2

インスタンス メソッドだけでなく、適切なライブラリを使用して CLOS スタイルのジェネリック メソッドを使用することもできます。Laurent Deniau の COS ライブラリ(論文[リンク]#includeも参照) は、すぐに使い始めることができる完全な OO システムを提供します。メソッドの構文は、他の関数呼び出しよりも重くありません。

それも明らかに高速です。著者は、Objective-C で表現された同様のコードでパフォーマンスの優位性を獲得したと主張しています (その主張自体には少し塩を足して考えますが、たとえそれらが同等であったとしても、それは印象的です)。

于 2013-06-28T00:56:50.650 に答える
1

OO メソッド呼び出しをエミュレートするには、クラスまたは vtable ポインターを持つオブジェクトが必要です。たとえば、関数ポインターを含む構造体を指すメンバーが含まれている場合、そのうちの 1 つが であるlist_t場合、使用法は次のようになります。funcsadd

list->funcs->add(list, data)

可変引数マクロでキャプチャできるもの:

#define OO(obj, func, ...) (obj)->funcs->func(obj, __VA_ARGS__)

OO(list, add, data);
于 2013-06-27T09:18:09.660 に答える
0

簡単なものが必要な場合は、ブロック言語拡張機能を使用して構造体メンバー関数を実装できます。ここにブログを書きました。

ブロックを使用して、関連する構造体をラムダ キャプチャし、 thisポインターをシミュレートできます。

このアプローチには仮想ディスパッチがないため、これらの真のオブジェクトを考慮するかどうかはあなた次第です。

于 2013-06-28T01:53:30.053 に答える