1

次の簡単なコードをご覧ください。

class A
{
public:
    A() {}
    virtual bool cmp(const A& a) const {cout << "cmp A" << endl; return true;}
};
class B : public A
{
public:
    B() {}
    ~B() {}
    bool cmp(const B& b) const {cout << "cmp B" << endl; return false;;}
};


int main()
{

    A a1;
    A a2;
    B b1;
    B b2;

    a1.cmp(a2); // as expected
    b1.cmp(b2); // as expected

    a1.cmp(b1); // upcasting
    // b2.cmp(a2); // conversion needed


    // Here is the problematic part:
    A* pa;
    pa = new B;

    pa -> cmp (b1); // Why why why the cmp of A runs?

    return 0;
}

私はそれを理解できません.vptrとvtbl、およびキャストなしで呼び出しに正確に一致する関数があります。では、なぜクラス A の cmp が呼び出されるのでしょうか。

論理的な答えは大歓迎です。

4

7 に答える 7

3

演算子をオーバーライドしていないためです。あなたのクラスには 2 人の異なるオペレーターがいます。

メソッドまたは演算子をオーバーライドするには、署名が完全に一致する必要があります。つまり、次のことを意味します。

  • 名前
  • パラメーター
  • cv修飾子

基本クラスの演算子はconst A&パラメーターとして を受け取り、派生クラスはconst B&.

于 2012-08-24T14:06:20.060 に答える
1

A::cmpB::cmp署名が一致しないためです。

Andb1は最初に変換されconst A &A::cmp呼び出されます

于 2012-08-24T14:07:01.910 に答える
1

2 つのオーバーライドがあります

A::cmp(const A&)
B::cmp(const B&)

したがって、コンパイル時にpaのタイプがAであるため、実行するpa->cmp()と呼び出されます。A::cmp何もオーバーライドしていないため、ここでは vptr のポイントはありません。

あなたが持っている場合、それはオーバーライドされます

bool B::cmp(const A& b)

署名を上書きするA::cmp(const A& b)

于 2012-08-24T14:07:14.233 に答える
0

bool cmp(const B& b) constは、基本クラスの仮想メソッドをオーバーライドしないため、署名が異なるため、これは予想どおりです。

于 2012-08-24T14:07:45.047 に答える
0

B::cmp()とはサインが違うのでA::cmp()。だからB::cmp()オーバーライドしていませんA::cmp()が、それを隠しています。それは仮想ではなく、呼び出しによって認識されませんA*

于 2012-08-24T14:08:13.943 に答える
0

B のメソッドは基本クラス メソッドを「隠している」ため、B からは見えません。詳細な説明については、 C++ FAQを参照してください。

于 2012-08-24T14:10:33.673 に答える
0

共変の戻り値の型はオーバーライド仮想関数で許可されていますが、共変の引数の型は許可されていないことに注意してください。したがって、基本仮想関数をオーバーライドするのではなく、非表示にします。

于 2012-08-24T14:17:49.527 に答える