2017年12月18日
《その185》 仮想関数,多相的クラス
仮想関数
まず、今回のプログラムの概略です。
基底クラス Base と、Base の public派生クラス Der1, Der2 があります。それぞれのクラスのメンバ関数 statement は仮想関数("virtual"が付加されている,関数名が同じ,仮引数が同じ)です。
main関数では、
Base型のオブジェクト bas
Der1型のオブジェクト de1
Der2型のオブジェクト de2
を作成し、各オブジェクトを引数にして、関数 print を呼び出します。関数 print は、それらのオブジェクトへの参照を受け取ります。
関数 print(Base& x); は、Base&型の仮引数で各オブジェクトへの参照を受け取ります。
そして、受け取った参照先オブジェクトの動的な型に応じた仮想関数 statement が呼び出されることになります。
bas の動的な型は Base型なので、呼び出されるのは Base::statement()
de1 の動的な型は Der1型なので、呼び出されるのは Der1::statement()
de2 の動的な型は Der2型なので、呼び出されるのは Der2::statement()
となります。
また、関数 print(Base& x); は、
各オブジェクトの型を、typeid演算子を用いて出力します。
typeid演算子が返す型については、下記の多相的クラスの項目をご覧ください。
多相的クラス
仮想関数を含むクラスは、多相的クラスと呼ばれる特殊なクラスです。
クラス Base は、仮想関数 statement を持っている
クラス Der1 は、仮想関数 statement を持っている
クラス Der2 は、仮想関数 statement を持っている
ので、すべて多相的クラスということになります。
多相的クラスであるため、関数 print(Base& x); の仮引数 x の参照先の型は、動的な型であると解釈されます。
typeid演算子は、その動的な型を返却します。
下記のプログラムの出力結果は、次のようになります。
また、もし、各クラスの virtual print(Base& x); から virtual を取り除いて、仮想関数ではない状態にした場合の、出力結果は、次のようになります。
// ------------------------------------
#include <typeinfo>
#include <iostream>
using namespace std;
class Base {
int a;
public:
Base(int x = 10) : a(x) { }
int get_a() const { return a; }
// 仮想関数
virtual void statement() const {
cout << "基底クラス Base\n";
}
};
class Der1 : public Base {
int b;
public:
Der1(int x = 20, int y = 22)
: Base(x), b(y) { }
int get_b() const { return b; }
// 派生クラスの "virtual" は省略可能です。
virtual void statement() const {
cout << "派生クラス Der1\n";
}
};
class Der2 : public Base {
int c;
public:
Der2(int x = 30, int y = 33)
: Base(x), c(y) { }
int get_c() const { return c; }
// 派生クラスの "virtual" は省略可能です。
virtual void statement() const {
cout << "派生クラス Der2\n";
}
};
void print(Base& x) {
x.statement();
cout << typeid(x).name() << '\n';
}
int main() {
Base bas;
Der1 de1;
Der2 de2;
print(bas); cout << '\n';
print(de1); cout << '\n';
print(de2);
}
// ------------------------------------
この記事へのコメント
コメントを書く
この記事へのトラックバックURL
https://fanblogs.jp/tb/7101908
※ブログオーナーが承認したトラックバックのみ表示されます。
この記事へのトラックバック