アフィリエイト広告を利用しています

広告

この広告は30日以上更新がないブログに表示されております。
新規記事の投稿を行うことで、非表示にすることが可能です。
posted by fanblog

2017年12月19日

《その189》 仮想関数テーブル


 仮想関数テーブル

 次の (1), (2) のプログラムの相違点は、基底クラス Aaa のメンバ関数 f が仮想関数であるかないかだけです。
具体的には、Aaa のメンバ関数 f() の前に "virtual" が付いているかいないかの違いです。


 (1) には "virtual" があるので、Aaa&型参照 ref の参照先 obj_b の型は 動的な型 Bbb であり、関数 f() を呼び出した場合には Bbb::f() が呼ばれます。

 多相的クラスには、最終オーバライダ(派生により最終的にオーバライドされた関数)へのポインタを記録した仮想関数テーブルが用意されており、プログラムは、そのテーブルを参照して Bbb::f() を呼び出します。
 多相的クラスのオブジェクトは、そのクラス用の仮想関数テーブルへのポインタを持っていますから、各オブジェクトは、必要な時に、仮想関数テーブルを参照できるわけです。

 仮想関数を利用する場合には、このように、各オブジェクトが仮想関数テーブルへのポインタ用の領域を持ち、さらに、仮想関数テーブルも記憶域を占有しますから、メモリの消費がその分だけ増加します。


 (2) には "virtual" がないので、Aaa&型参照 ref の参照先 obj_b の型は 静的な型 Aaa であり、関数 f() を呼び出した場合には Aaa::f() が呼ばれます。


プログラム(1) 仮想関数有りの場合

// ------------------------------------
#include <typeinfo>
#include <iostream>
using namespace std;

class Aaa {
public:
virtual void f() { cout << "Aaa::f()" << '\n'; }
};

class Bbb : public Aaa {
public:
void f() { cout << "Bbb::f()" << '\n'; }
};

int main() {
Bbb obj_b;
Aaa& ref = obj_b;

cout << typeid(obj_b).name() << '\n';
// obj_b は常に class Bbb型です。

cout << typeid(ref).name() << '\n';
// クラス Bbb は多相的クラス(仮想関数を有するクラス)なので、
// Bbb型オブジェクト obj_b への
// Aaa&型の参照 ref は、動的な型
// Bbb です。


obj_b.f();
// Bbb::f() が呼び出されます。

ref.f();
// f() が仮想関数なので、Bbb::f() が呼び出されます。
}
// ------------------------------------

f05_0007.png


プログラム(2) 仮想関数無しの場合

// ------------------------------------
#include <typeinfo>
#include <iostream>
using namespace std;

class Aaa {
public:
void f() { cout << "Aaa::f()" << '\n'; }
};

class Bbb : public Aaa {
public:
void f() { cout << "Bbb::f()" << '\n'; }
};

int main() {
Bbb obj_b;
Aaa& ref = obj_b;

cout << typeid(obj_b).name() << '\n';
// obj_b は常に class Bbb型です。

cout << typeid(ref).name() << '\n';
// クラス Bbb は多相的クラスではないので、
// Bbb型オブジェクト obj_b への
// Aaa&型の参照 ref は、静的な型
// Aaa です。


obj_b.f();
// Bbb::f() が呼び出されます。

ref.f();
// Aaa::f() が呼び出されます。
}
// ------------------------------------

f05_0008.png


新版 明解C 入門編 (明解シリーズ)

新品価格
¥2,916から
(2017/11/10 13:13時点)

新版 明解C 中級編 (明解シリーズ)

新品価格
¥2,916から
(2017/11/10 13:14時点)





《その188》 ポリモーフィズム


 ポリモーフィズム(多相性)

 下記のプログラムには、クラスが3つあります。
Aaaは基底クラス、Bbb,Ccc は Aaa のpublic派生クラスです。

【 基底クラス Aaa 】
 仮想メンバ関数 f は、仮引数 n が奇数であるか偶数であるかを判断します。

【 派生クラス Bbb 】
 メンバ関数 f は、Aaa の仮想メンバ関数 f をオーバライドしています。
クラス Bbb の関数 f は、仮引数 n が 3 の倍数であるかどうかを判断します。

【 派生クラス Ccc 】
 オーバライダ f は、仮引数 n が 10以上か 10未満かを判断します。
 ※ オーバライドした関数は、オーバライダと呼ばれます。


【 関数 func(Aaa& x, int n) 】
 3つの型すべてのオブジェクトへの参照を、仮引数 x で受け取ることができます。


【 main関数 】
 次のことをします。
・ユーザから整数 n を受け取る。
・Aaa型のオブジェクト obj_a を生成。
・Bbb型のオブジェクト obj_b を生成。
・Ccc型のオブジェクト obj_c を生成。
・関数 func に obj_a と 整数 n を渡す。
・関数 func に obj_b と 整数 n を渡す。
・関数 func に obj_c と 整数 n を渡す。


 3つのクラスオブジェクト obj_a, obj_b, obj_c はそれぞれ型が異なっていますが、基底クラス型が Aaa型という共通点を利用して、同じ扱いができます。
メッセージを受け取った各オブジェクトは、それぞれ自身の動的な型に応じた振舞いをします


 ポリモーフィズム(多相性)

 多相的クラス( 当ブログの《185》)オブジェクトは、派生による階層関係を持っています。このような関係にある複数のクラスオブジェクトに対して、次のことが可能になります。

基底クラスが同一であるので、基底クラス型への参照(あるいはポインタ)を通じて、型の異なる複数のオブジェクトに同じメッセージを送ることができます。

メッセージを受け取った各オブジェクトは、自身の動的な型に応じた振舞いをします。

このような手法(考え方・方針)をポリモーフィズムと呼んでいます。


// ------------------------------------
#include <iostream>
using namespace std;

class Aaa {
public:
virtual void f(int n) const {
cout << n << " は"
<< ( n % 2 ? "奇数" : "偶数" )
<< "です。\n";
}
};

class Bbb : public Aaa {
public:
void f(int n) const {
cout << n << " は 3 の倍数で"
<< (n % 3 ?
"はありません。" : "す。")
<<'\n';
}
};

class Ccc : public Aaa {
public:
void f(int n) const {
cout << n << " は 10 "
<< (n < 10 ? "未満" : "以上")
<< "です。\n";
}
};

void func(Aaa& x, int n) {
x.f(n);
}

int main() {
int n;
cout << "整数を入力 : "; cin >> n;
Aaa obj_a; Bbb obj_b; Ccc obj_c;
func(obj_a, n);
func(obj_b, n);
func(obj_c, n);
}
// ------------------------------------

f05_0006.png


新版 明解C 入門編 (明解シリーズ)

新品価格
¥2,916から
(2017/11/10 13:13時点)

新版 明解C 中級編 (明解シリーズ)

新品価格
¥2,916から
(2017/11/10 13:14時点)






 たまに、クリック お願いします m(_ _)m

 AA にほんブログ村 IT技術ブログ C/C++へ

こうすけ:メール kousuke_cpp@outlook.jp

【1】★★C++ 記事目次★★ ← 利用可能です。
・新版明解C++入門編 / 新版明解C++中級編
・その他 C++ 関連記事

【2】★★こうすけ@C#★★
・C# の初歩的な記事


検索
<< 2017年12月 >>
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
プロフィール
こうすけさんの画像
こうすけ

 たまに、クリック お願いします m(_ _)m

 AA にほんブログ村 IT技術ブログ C/C++へ

こうすけ:メール kousuke_cpp@outlook.jp

【1】★★C++ 記事目次★★ ← 利用可能です。
・新版明解C++入門編 / 新版明解C++中級編
・その他 C++ 関連記事

【2】★★こうすけ@C#★★
・C# の初歩的な記事


×

この広告は30日以上新しい記事の更新がないブログに表示されております。