仮想関数・virtualキーワード

スポンサーリンク
スポンサーリンク
ライフスタイル関連のコンテンツ
お金 | 仕事 | 勉強 | プライベート | 健康 |
プログラミング関連のコンテンツ
C言語/C++入門 | Ruby入門 | Python入門 | プログラミング全般

virtualキーワードを指定することで、オーバーライドするメンバ関数を区別することができます。
例を見たほうが簡単です。

スポンサーリンク

#include <iostream>
 
class parent {
public:
    void a() { std::cout << "parent.a()\n"; }
    virtual void b() { std::cout << "parent.b()\n"; }
    virtual void c() { std::cout << "parent.c()\n"; }
};
 
// parentクラスを継承
class child : public parent {
public:
    void a() { std::cout << "child.a()\n"; }
    void b() { std::cout << "child.b()\n"; }
};
 
void call_parent(parent& obj) {
    obj.a();
    obj.b();
    obj.c();
}
 
// メインルーチン
int main() {
    // childクラス(子)のインスタンスでテスト
    // childはparentを継承後、メンバ関数をオーバーライド
    child child_ist;
 
    child_ist.a();
    child_ist.b();
    child_ist.c();
    std::cout << "\n";
 
    // parentクラス(親)のインスタンスでテスト
    parent parent_ist;
 
    parent_ist.a();
    parent_ist.b();
    parent_ist.c();
    std::cout << "\n";
 
    // child型の変数を、parent型に渡してcall_parent()でテスト
    // b(), c()はparentでvirtualキーワード
    call_parent(child_ist);
 
    return 0;
}

1.childクラス(子)のインスタンスでテスト

a(), b()はchildクラスで定義されているので、オーバーライドされます。
子クラスをインスタンス化した場合、子クラス→親クラスとメンバが検索されます。
c()はchildクラスで定義されていないので、parentのメンバ関数が検索されます。
c()は、parentクラスで定義されているので継承により、「parent.c()」を出力することとなります。

2.parentクラス(親)のインスタンスでテスト

親クラスのインスタンスは、そのまんまです。
親クラスのみが検索されます。

3.child型の変数を、parent型に渡してcall_parent()でテスト

子クラスの型でインスタンス化した変数を、親クラスの型の変数として扱うことができます。
この場合、親クラス内でvirtualキーワードで仮想関数として宣言してあるメンバ以外は、親クラスから子クラスを見ることができなくなります。
すなわち・・・

virtual void b() { std::cout << "parent.b()\n"; }
virtual void c() { std::cout << "parent.c()\n"; }

と、parentクラスのb(), c()のメンバ関数は、子クラスによりオーバーライドされます。
しかし、c()は子クラスchildでは定義されていませんので、parentクラスのメンバ関数が、そのまま実行されます。

実行結果。

child.a()
child.b()
parent.c()
 
parent.a()
parent.b()
parent.c()
 
parent.a()
child.b()
parent.c()
スポンサーリンク
 
スポンサーリンク