8

私は、前方クラス宣言とそのようなクラスへのポインターを定期的に使用します。

関数ポインターを多数のレイヤーに渡す必要があります。関数ポインターのプロトタイプを宣言するヘッダーは、単にそのポインター値を渡す各レイヤーではなく、関数ポインターを逆参照するモジュールにのみ含めることをお勧めします。

これは可能ですか?

=====

回答から、私は質問によって十分に明確に表現していないと思います。私は前方クラス宣言に類似したものを探しています。私は皆、私が書くことができることに同意します:

クラス foo;

ボイドバー (foo*);

無効 waz(foo* p) { bar(p); }

waz は名前以外にクラス foo について何も知らないことに注意してください。おそらく、bar は foo の完全な説明にアクセスできます。おそらく、bar は単純に p をさらに先に渡します。誰も気にしない?foo* を逆参照するサイトのみ。他のすべてのサイトでは、「class foo;」のみが必要です。

同様に、私は次のように書けることを知っています:

typedef void foo(int, double);

ボイドバー (foo*);

無効 waz(foo* p) { bar(p); }

違いは、識別子 foo が関数型を示すことがわかっているだけでなく、完全な署名/プロトタイプをすでに持っていることです。これにより、次の 2 つの不快なシナリオのいずれかに陥ります。

1) 複数のサイトで typedef を複製します (ヤッ! 壊れやすい!) 2) typedef をヘッダーに貼り付け、foo* が言及されているすべての場所に含めます。

非対称性に注意してください。データ オブジェクトの場合、foo* を逆参照したいポイントでクラス foo の完全な説明を提供するだけで済みました。関数の場合、foo* に言及したいすべての場所で完全な署名/プロトタイプを提供する必要があります。

では、この非対称性を改善する方法はありますか?

4

6 に答える 6

4

追加の逆参照を犠牲にして、未定義の構造体型を使用してこれを行うことができます。

これをメインヘッダーファイルに入れます:

typedef struct FuncStruct *FuncPtr;

これは宣言しstruct FuncStructますが、フィールドを宣言しません。次に、この構造体へのポインタを宣言しますFuncPtr。sを渡すことはできFuncPtrますが、逆参照することはできません。

次に、特定のファイル(またはより具体的な .h ファイル)で、実際に次のstruct FuncStructように定義できます。

struct FuncStruct {
  int (*f)(int, char, double);
};

次に、この定義を過ぎたコードで a を逆参照しFuncPtrて、実際の関数ポインターを取得できます。

これは単なるキャストからの追加の逆参照であることに注意してください。これは、FuncStructs のメモリ管理を行う必要があることを意味します。

于 2010-04-04T03:30:52.980 に答える
3

関数ポインタを渡すために必要なのは、引数の型と戻り値の型だけです:

void f(void (*func)(int));

ここで、は、 を受け取り、を返すf()関数への関数ポインターを受け取る関数です。intvoid

typedefs より読みやすくします。

typedef void (*FuncPtr)(int);
void f(FuncPtr func);

一般に、ファンクターを調べたり、Boost.FunctionBoost.Bindなどを使用したりすることをお勧めします。そうすれば、バインドされたメンバー関数または関数オブジェクトを渡すこともできます。

void f(boost::function<void (int)> fn) {
    fn(42);
}

struct X {
    void f(int) {}
};

// ...
X x;
f(boost::bind(&X::f, &x, _1));
于 2010-04-04T03:19:43.753 に答える
0

確かに、例えば

typedef void (*FOOFUNC)(int x, int y, char z);

今、あなたはそれを渡すことができます

void foo(FOOFUNC f) {
  f(...);
}
于 2010-04-04T03:20:29.203 に答える
-1

あなたが何をしようとしているのか、あなたの質問からは明らかではありません。

まず、C++ には「プロトタイプ」というものはありません。「プロトタイプ」(関数プロトタイプ) の概念は、C 言語のみに固有のものです。

次に、メッセージ本文で「関数ポインターのプロトタイプ」について言及していますが、キャプションでは「関数プロトタイプ」について説明しています。これにより、さらに混乱が生じます。「関数ポインタのプロトタイプ」は意味がありません。C++ はおろか、C でもポインタの「プロトタイプ」などというものはありません。

それで、あなたは何をしたいですか?関数を前方宣言する場合は、宣言するだけです。

ポインターを前方宣言する場合は、宣言するだけです。オブジェクトの宣言 (非定義宣言) を取得するには、externキーワードで宣言するだけです。

于 2010-04-04T03:41:09.143 に答える
-1

完全に可能です。関数プロトタイプは必要な場所にコピーできますが、これが頻繁に行われるのを見ると警鐘が鳴り始めます。

于 2010-04-04T03:16:41.290 に答える