継承とポインタ


派生クラスのポインタ

以前オブジェクト型のポインタの説明をしました
C++では、クラス型の変数のポインタを生成することができます

さらに、なんとクラス型のポインタ変数には派生クラスのアドレスを代入できます
これは、オブジェクト指向未経験の方であればかなり斬新なものではないでしょうか

派生クラスは、基本クラスの情報を保有しています
つまり、基本クラスと型に互換性があるのでポインタに代入できるのです
#include <iostream>
using namespace std;

class Base {
public:
	char *str;
};

class Derived : public Base {
public:
	int i;
} obj ;

int main() {
	obj.str = "Kitty on your lap";

	Base *po = &obj;
	cout << po->str;

	return 0;
}
obj 変数は、Base クラスの派生クラス Derived のオブジェクトです
これに対しポインタ変数 po は Base クラス型のポインタ変数です
しかし、上のプログラムでは次のような代入を行っています

Base *po = &obj;

派生クラス Derived は、Base クラスのメンバを持っているためこれは有効です
基本クラスのポインタは、派生クラスのオブジェクトを指す事が可能なのです

ただし、基本クラスのポインタは基本クラスの情報しか持ちません
たとえ派生クラスのオブジェクトを指していても、派生クラスのメンバは呼び出せません
つまり、上のプログラムで po->i を参照した場合はコンパイルエラーになります

ポインタでこのようなことが可能ということは参照でも同じです
参照も、派生クラスのオブジェクト方を受け取ることができます
#include <iostream>
using namespace std;

class Base {
public:
	char *str;
};

class Derived : public Base {
public:
	int i;
} obj ;

void getRef(Base &obj) {
	cout << obj.str;
}

int main() {
	obj.str = "Kitty on your lap";
	getRef(obj);
	return 0;
}
getRef() 関数は Base 型のオブジェクトの参照を受け取ります
ポインタ同様に、派生クラスの参照を渡すことができます

この機能は、同名のメンバ名を持つクラス間で面白い現象が発生します
メンバ名が基本クラスと派生クラスで衝突している場合
クラスを明示しなかった場合は常に自分のクラスのメンバを優先しました

しかし、ポインタが指すオブジェクトは基本クラスの情報しかありません
そのため、基本クラスのメンバを呼び出すという現象が発生します
#include <iostream>
using namespace std;

class Base {
public:
	void paint() { cout << "Kitty on your lap\n"; }
};

class Derived : public Base {
public:
	void paint() { cout << "Di Gi Gharat\n"; }
} obj ;

int main() {
	Base *po = &obj;
	obj.paint();
	po->paint();

	return 0;
}
これをより発展させると、動的なポリモーフィズムが実現できます
このことを理解した上で、次の章からは高度なポリモーフィズムである
関数のオーバーライドについて、説明していきましょう



前のページへ戻る次のページへ