0

void *およびその他のポインター型を引数として取る C++ ポリモーフィズム関数: あいまいと見なされますか?

任意のポインターを にキャストできるため、以下のプログラムで期待される の代わりにvoid*以下の bar の 2 回目の呼び出しが実行されるのではないかと心配していますか?void bar(void*)void bar(int*)

g++ でテストしたところ、期待どおりに動作しました (つまり、int* は void* にキャストされません)。しかし、C++ 言語仕様に関して、この質問にコメント/回答できる人はいますか?

foo.h:

class Foo {
public:
    void bar(void *);
    void bar(int *);
};

main.cpp:

...
struct A *p1;
int *p2;
Foo foo;
...
foo.bar(p1);
foo.bar(p2);

さらに、たとえば、 第 1 形式として引数を取り、第 2 形式として基本抽象クラス ポインター引数をbar取る仮想ポリモーフィズム関数になりました。void*派生クラス ポインタを引数として呼び出した場合、第 1 形式と第 2 形式のどちらが実行されますか? つまり、派生クラス ポインターは、その基本抽象クラス ポインターにキャストされますか (したがって、2 番目のフォームが実行されます)、またはvoid *呼び出し前にキャストされます (したがって、1 番目のフォームが実行されます) bar()?

4

1 に答える 1

4

オーバーロードの解決ルール (セクション暗黙的な変換シーケンスのランキング)によると、引数はいずれかの関数のパラメーター型に変換できるため、この場合の最適な実行可能な関数は、暗黙的な変換が優れている関数になります。

為に:

class Foo {
  public:
    void bar(void*);
    void bar(int*);
};

// ...

Foo foo;
int* p2;
foo.bar(p2);

1 つ目はランク 3 (コンバージョン) で、2 つ目はランク 1 (完全一致) です。変換を必要としない完全一致は、変換よりも優れているため、 が呼び出されますvoid bar(int*)

ただし、2 番目のケースではより複雑になります。

class Foo {
  public:
    virtual void bar(void*);
    virtual void bar(Foo*);
    virtual ~Foo() = default;
};

class FooTwo : public Foo {};

// ...

Foo foo;
FooTwo footwo;

foo.bar(&footwo);

どちらもランク 3 (コンバージョン) であるため、これはコンバージョン ランキング ルールに従います。両方のコンバージョンのコンバージョン ランクが同じであるため、これは拡張コンバージョン ランキング ルールに適用されます。拡張ルール 2 には次のように記載されています。

ポインターから派生物への変換をポインターからベースへの変換は、ポインターから派生物へのポインターから void への変換よりも優れており、ポインターからベースへの変換から void への変換は、ポインターから派生物への変換よりも優れています。無効にする。

これをvoid bar(Foo*)考慮すると、 は よりも一致すると見なされます。void bar(void*)つまり、 によって選択されfoo.bar(&footwo);ます。

後者の例については、こちらを参照してください。

于 2016-07-04T18:41:05.243 に答える