2

仮想関数の再定義と使用の違いは何ですか?それらは同じ目的を果たしませんか?どちらの場合も、派生クラスのオブジェクトが同じ名前で関数の独自のバージョンを呼び出すことを許可しています。違いはどこにありますか?

4

3 に答える 3

5

例はそれを最もよく言います:

#include <iostream>

using namespace std;

class A {
public:
  virtual void f1() { cout << "Class A" << endl; }
  void f2() { cout << "Class A" << endl; }
  virtual ~A(){}
};

class B : public A {
public:
  virtual void f1() { cout << "Class B" << endl; }
  void f2() { cout << "Class B" << endl; }
  virtual ~B(){}
};

int main()
{
  A *a = new B;
  a->f1();
  a->f2();
}

..。

$ ./override 
Class B
Class A

Bのインスタンスを参照すると、f1()まだB'sバージョンを呼び出しますが、'sf2()を呼び出していることがわかりますA

関数virtualを宣言するとき、それを呼び出すときは、vtableを使用して、呼び出す関数の正しいバージョンを検索する必要があると言っています。したがって、参照する場合でも、関数の最も派生したバージョンを常に取得できます。祖先型として。仮想がない場合は、参照しているタイプの定義を使用するだけです。

于 2013-03-20T03:32:47.923 に答える
3

違いは、基本クラスへの参照またはポインタがある場合です。仮想関数を呼び出すと、最も派生したバージョンが呼び出され、通常の関数を呼び出すと、基本クラスのバージョンが呼び出されます。

変数を直接使用している場合、または最も派生したクラスへの参照またはポインターを使用している場合、実際的な違いはありません。

于 2013-03-20T03:29:56.063 に答える
2

TL; DR

C ++のポリモーフィズムを利用する唯一の方法は、仮想関数とポインター(および参照)を使用することです。virtualキーワードは、子クラスの動的型を持つ基本クラスへのポインターを処理するときに呼び出す仮想関数のバージョンを決定するときに、どこを探すかを仮想関数テーブルに割り当てるようにコンパイラーに指示します。

C++でポリモーフィズムはどのように機能しますか

簡単な例を見てみましょう。

class A { public: virtual void eat() { std::cout << "Class A" << std::endl; }
class B : public A {};
class C : public B { virtual void eat() { std::cout << "Class C" << std::endl; }

注:最初の関数/メソッド定義の後で、virtualキーワードを省略できます。

以下:

A a; B b; C c;
A* ptrA = &a; A* ptrB = &b; A* ptrC = &c;
ptrA->eat();
ptrB->eat();
ptrC->eat();

印刷されます:

Class A
Class A
Class C

関数virtualを宣言しなかった場合eat、出力は単純に次のようになります。

Class A
Class A
Class A
于 2013-03-20T03:40:30.543 に答える