Hello関数がなく、mainでob.displayを呼び出すだけで、クラスAではなくクラスBのdisplay関数を呼び出すとします。
関数display()の呼び出しは、基本クラスで定義されたバージョンとしてコンパイラーによって一度設定されています。これは、関数呼び出しの静的解決、または静的リンケージと呼ばれます。関数呼び出しは、プログラムが実行される前に修正されます。これは、プログラムのコンパイル中にdisplay()関数が設定されるため、アーリーバインディングと呼ばれることもあります。
では、基本クラスの表示関数の前に仮想キーワード(遅延バインディング)を使用せずに、派生クラスの表示関数を呼び出すにはどうすればよいでしょうか。
このプログラムでは、オブジェクトを値による呼び出し、ポインターによる呼び出し、およびHello関数への参照による呼び出しとして渡すことが正常に機能します。ここで、ポリモーフィズムを使用し、派生クラスのメンバー関数が呼び出された場合にそれを表示する場合は、ベースの表示関数の前に仮想キーワードを追加する必要があります。ポインタによる呼び出しと参照による呼び出しによってオブジェクト値を渡す場合、派生クラスの関数を呼び出しますが、値によってオブジェクトを渡す場合、それはなぜそうではありませんか?>
class A
{
public:
void display(); // virtual void display()
{
cout << "Hey from A" <<endl;
}
};
class B : public A
{
public:
void display()
{
cout << "Hey from B" <<endl;
}
};
void Hello(A ob) // &ob //*ob
{
ob.display(); // ob->display()
}
int main()
{
B obj;
Hello(obj); // obj //&ob
return 0;
}
では、基本クラスの表示関数の前に仮想キーワード(遅延バインディング)を使用せずに、派生クラスの表示関数を呼び出すにはどうすればよいでしょうか。
非仮想関数は、呼び出されたオブジェクト(または参照またはポインター)の静的型に応じて、コンパイラーによって単純に解決されます。したがって、派生型のオブジェクトとそのサブオブジェクトへの参照が与えられます。
B b;
A & a = b;
非仮想関数を呼び出すと、異なる結果が得られます。
b.display(); // called as B
a.display(); // called as A
実際のタイプがわかっている場合は、そのバージョンを呼び出すように指定できます。
static_cast<B&>(a).display(); // called as B
しかし、a
参照するオブジェクトにタイプがない場合、それはひどく間違ってしまいますB
。
ここで、ポリモーフィズムを使用し、派生クラスのメンバー関数が呼び出された場合にそれを表示する場合は、ベースの表示関数の前に仮想キーワードを追加する必要があります。
正しい。関数を仮想化すると、別のタイプの参照またはポインターを使用してアクセスする場合でも、オブジェクトの動的タイプに従って実行時に解決されます。したがって、上記の両方の例では、これをと呼びますB
。
ポインタによる呼び出しと参照による呼び出しによってオブジェクト値を渡すと、派生クラスの関数が呼び出されますが、値によってオブジェクトを渡すと、なぜそうならないのでしょうか。
値で渡すと、スライスすることになります。A
オブジェクトの一部だけをコピーして、タイプが新しいオブジェクトを作成しますA
。したがって、関数が仮想であるかどうかに関係なく、そのオブジェクトで関数を呼び出すとA
バージョンが選択されます。A
これは、であり、に過ぎないためA
です。
参照またはポインタを渡す場合でも、動的タイプの元のオブジェクトにアクセスしていますB
。したがって、仮想関数呼び出しはB
バージョンに解決されます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加