6

重複の可能性:
オーバーロードされた関数へのポインターを指定する方法は?

次のように定義されたクラスを持つライブラリがあります。

struct ClassA
{
    static ClassA foo(long);
    static ClassA foo(double);
}

これらの両方の関数のアドレスを取得する必要があります。私が現在試しているコードはエラーC2440を出します:'overloaded-function'から'...'に変換できません

ns::ClassA (ns::ClassA::*ClassA_foo1)(long) = &ns::ClassA::foo;
ns::ClassA (ns::ClassA::*ClassA_foo2)(double) = &ns::ClassA::foo;

それらが静的であるという事実かもしれないと思いましたが、return型の前または後に静的を配置すると同じエラーが発生します。

4

3 に答える 3

5

関数がオーバーロードされているという事実は、実際には関係ありません。ここでの本当の問題は、関数ポインターとメンバー関数ポインターの違いです。オーバーロードせずにいくつかの例を実行します。

static解決策:メンバー関数として定義するには、を削除します。または、に置き換えns::ClassA::*ClassA_foo1ます*ClassA_foo1。後者が欲しいと思います。typedef(しかし、他の人がすでに示唆しているように、私は実際に使用することをお勧めします)。

次の2つを検討してください。

namespace ns {
struct ClassA
{
    static ClassA foo(long);
};
}

namespace ns {
struct ClassA
{
    ClassA foo(long);
};
}

前者の場合、fooはstatic典型的な関数であり、したがって、関数ポインターに格納できます。

ns::ClassA (ClassA_foo1)(long) = &ns::ClassA::foo;

を削除するstaticと、それは関数ではなくなり、メンバー関数になります。また、メンバー関数へのポインターは関数へのポインターとは異なりthis、メソッドが呼び出されるオブジェクトとなるオブジェクトを使用して実行する必要があります。

関数ポインタの型には、戻り値の型とパラメータの型が含まれます。ただし、メンバー関数へのポインタの型には、オブジェクトの型も含まれている必要があります。型のオブジェクトにthis対してからメソッドを実行できるとは期待できません。CircleBankAccount

関数へのポインタの宣言:

 ReturnType (*variable_name) (PARAM1, PARAM2)

メンバー関数へのポインターの宣言:

 ReturnType (ThisObjectType::*variable_name) (PARAM1, PARAM2)

この最後の行は興味深いものです。一見すると、それR (A::*v) (P1,P2)は通常の関数ポインタを宣言し、結果の変数vAスコープに配置すると思うかもしれません。しかし、そうではありません。代わりに、型のオブジェクトを操作するメンバー関数へのポインタを定義しますA

于 2012-08-31T18:55:47.350 に答える
4

あなたが観察している問題は、関数がオーバーロードされているという事実とはまったく関係がありません。オーバーロードされていない関数でも同じエラーが発生します。

静的メンバー関数には通常の関数型があります。その間、あなたはそれらをメンバー関数型の関数として解釈しようとしています。これにより、コンパイラから報告されるポインタ型の不一致が発生します。これは、まったく同じ理由でコンパイルに失敗する簡単な例です。

struct S {
  static void foo();
};
...
void (S::*p)() = &S::foo; // ERROR, pointer type mismatch

つまり、ポインターは、メンバー関数へのポインター型のポインターとして宣言されます。このようなポインターは、静的メンバー関数のアドレスを保持できません。静的メンバー関数と非静的メンバー関数は、まったく異なる性質の獣です。対応するポインタタイプは互換性がなく、相互に変換できません。それがあなたのエラーの理由です。

これはおそらくそれが見えるはずだった方法です

ns::ClassA (*ClassA_foo1)(long) = &ns::ClassA::foo;
ns::ClassA (*ClassA_foo2)(double) = &ns::ClassA::foo;

つまり、左側のポインタは、メンバー関数ポインタとしてではなく、通常の関数ポインタとして宣言する必要があります。

于 2012-08-31T19:05:13.640 に答える
0
ns::ClassA (ns::ClassA::*ClassA_foo1)(long) = &ns::ClassA::foo;
ns::ClassA (ns::ClassA::*ClassA_foo2)(double) = &ns::ClassA::foo;

静的メンバーのペアをファイルスコープで設定しようとしているようClassA_foo1ですClassA_foo2。その場合、これは有効な構文ではありません。静的メンバーを定義するための構文は次のとおりです。

SomeType ClassName::member = initializer;

typedefを使用して宣言し、定義するのが最善ClassA_foo1ですClassA_foo2

struct ClassA {
   typedef ClassA (*ClassALongGenerator) (long);
   typedef ClassA (*ClassADoubleGenerator) (double);

   static ClassALongGenerator ClassA_foo1;
   static ClassADoubleGenerator ClassA_foo2;
};

次に、いくつかのソースファイルのファイルスコープで

ns::ClassALongGenerator ClassA_foo1 = ns::ClassA::foo;
ns::ClassADoubleGenerator ClassA_foo2 = ns::ClassA::foo;
于 2012-08-31T18:29:58.833 に答える