ぷらねギアのぶろぐ

プログラミング・組み込み・モノづくり等(予定)

アップキャスト-派生クラスのインスタンスの引渡しについて

オブジェクト指向についてまだまだ初心者ですが,ちょっとした気付きをメモ.

 

クラスのあるメンバ関数を毎回実行させるような仕様にしたい際には,引数にインスタンスを入れ,関数内でそのメンバ関数を実行する.これにより,渡したインスタンスメンバ関数を実行することができる.

引き渡すインスタンスは型にしたクラスを継承した派生クラスでも同様にメンバ関数を実行することができる.ただし,呼び出されるのは親クラスのメンバ関数

 

引き渡したインスタンスのクラスでオーバーライドしたメンバ関数を実行するためにはその親クラスのメンバ関数を仮想関数にしておく必要がある模様.

 

以下サンプルコード 

#include<iostream>

//親クラス
class Hoge{
public:
virtual void run0(); //メンバ関数(仮想関数)
void run1(); //メンバ関数
};
void Hoge::run0(){
 std::cout << "run0 :This is Hoge class" << std::endl;
}
void Hoge::run1(){
 std::cout << "run1 :This is Hoge class" << std::endl;
}

//子クラス
class Koge :public Hoge{
 public:
  void run0();//メンバ関数(オーバーライド)
  void run1();//メンバ関数(オーバーライド)
};

void Koge::run0(){
 std::cout << "run0 :This is Koge class" << std::endl;
}

void Koge::run1(){
 std::cout << "run1 :This is Koge class" << std::endl;
}

//孫クラス
class Loge :public Koge{
 public:
  void run0();//メンバ関数(オーバーライド)
  void run1();//メンバ関数(オーバーライド)
};

void Loge::run0(){
 std::cout << "run0 :This is Loge class" << std::endl;
}
void Loge::run1(){
 std::cout << "run1 :This is Loge class" << std::endl;
}

void hogefunc(Hoge &a){
 a.run0();//メンバ関数のrun0を実行(親クラスでは仮想関数)
 a.run1();//メンバ関数のrun1を実行
}

int main(){
 Koge k;//子クラスのインスタンス生成
 Loge l;//孫クラスのインスタンス生成
  hogefunc(k);//子クラスのインスタンスを引渡し
 hogefunc(l);//孫クラスのインスタンスを引渡し
}
メンバ関数run0()は親クラスHogeにおいて仮想関数として宣言,メンバ関数run1()は仮想関数ではない.このHogeクラスを継承した子クラスKogeと孫クラスLogeでは2つのメンバ関数をオーバーライドしている.
また関数hogefunc()では型が親クラスHogeインスタンスを引数とし,関数内で引数のメンバ関数run0()とrun1()を実行させている.
これを実行させると
> ./hoge.out
run0 :This is Koge class
run1 :This is Hoge class
run0 :This is Loge class
run1 :This is Hoge class
このように子クラス・孫クラスどちらとも親クラスで仮想関数としたrun0()は渡したインスタンスのクラスでオーバーライドしたメンバ関数が実行されているのに対し,そうではないrun1()では親クラスのメンバ関数が実行されていることがわかる.
インスタンスを渡して派生クラスに応じて使い分けたい場合には,親クラスで仮想関数にしなくてはいけない(らしい).
(ややこしいな...) 

間違いがあったらごめんなさい.