11

サブクラス化とメソッドの使用に問題があります。

クラスのインスタンスを作成し、Bそれをへのポインタとして保存しますA。しかし、ポインタを使用してオーバーロードされたメソッドを呼び出すと、出力は「B」ではなく「A」になります。なんで?

これは他の言語でも機能しますが、何が間違っていますか?

#include <iostream>
using namespace std;

class A {
public:
    void f() {
        cout << "A";
    }
};

class B : public A {
public:
    void f() {
        cout << "B";
    }
};

int main() {
    A *a = new B();
    a->f();
    return 0;
}
4

4 に答える 4

22

f()virtual基本クラスAで宣言する必要があります。

class A {
public:
    virtual void f() {
        cout << "A";
    }
};

すでに使用している他の言語はデフォルトで仮想メソッドになっている可能性がありますが、C ++はそうではありません(使用していないものにお金を払わないでください。仮想メソッドを呼び出すと間接参照が発生するため、通常のメソッド呼び出しよりも少し遅くなります) 。

を追加することによりvirtual、バインディングは実行時に延期され(動的バインディングと呼ばれます) 、値のタイプに基づいてどのf()関数呼び出しが決定されます。

関数を仮想として宣言していないためf()、バインディングは静的(コンパイル時)であり、変数のタイプ(値ではない)を使用してどちらf()を呼び出すかを決定します。したがって、現在のコードでは、はクラスへのポインタであるため、ステートメントはクラスa->f();を呼び出します。Af()aA

于 2013-02-18T15:10:28.153 に答える
6

ポリモーフィックな振る舞いを実現するには、基本クラスのメソッドはである必要がありますvirtual

したがって、に変更するclass A必要があります。void f()virtual void f()

于 2013-02-18T15:09:29.817 に答える
2

virtual関数をオーバーライドできるように宣言する必要があります。

#include <iostream>
using namespace std;

class A {
public:
    virtual void f() {// Here you must define the virtual.
        cout << "A";
    }
};

class B : public A {
public:
    virtual void f() { //Here the "virtual" is optional, but a good practice
        cout << "B";
    }
};

int main() {
    A *a = new B();
    a->f();
    return 0;
}
于 2013-02-18T15:20:36.300 に答える
0

基本クラスへのポインタがない場合にこの問題に直面する可能性がありますが、その実際のインスタンス(この質問の例には適用されません)

私の場合、クラスTokenとそのサブクラスがありましたWord

class Token {
   public: virtual string toString() { ... }
}
class Word: public Token {
   public: string toString() { ... }
}

それらを格納し、std::map<string, Token>そこから取得するには、Word::toString()次のようなコードを呼び出すことを期待していました。

std::map<string, Token> words;
words.insert("test", Word(...));
words["test"].toString();

代わりに私はToken::toString()毎回電話をしました。

解決策:このようなポインターを使用しstd::map<string, Token*>、すべてのインスタンスをポインターとして扱う(TBH、私はすでにポインターが嫌いです)

于 2020-10-19T21:33:35.400 に答える