継承の仕方(実装編)

inheritance-howto.png

親クラスを引き継ぐとどうなるか?

親の修飾子 Java C++
親のpublic関数の呼び出し そのまま使える
親のpublicメンバ 読み書き可能
親のprivateメンバ アクセス不可能
親のprotectedメンバ 子クラスでもprotected扱い。同じパッケージ内なら自由にアクセス可能 子クラスでprivate変数扱いになる
親クラスと同じ名前の変数を作った場合 親クラスの変数は無視され、子クラスの変数が呼ばれる
親クラスと同じ名前の関数を作った場合 親クラスの関数は無視され、子クラスの関数が呼ばれる

Javaの場合、@Overrideつけてもつけなくてもオーバーライドできるけど、
だったら@Overrideの存在意義ってなんだ??
virtualも同様に、なんのためにあるんだ?
子クラスは親クラスのメソッドをそのまま使うことができる。(親クラスでpublicの修飾子がついていれば)
親クラスのメソッド・変数でもprivateだったら使うことはできない。
親クラスのメソッドはvirtualをつければオーバーライドもできる。
virtualのついていない親クラスのメソッドと同じ名前のメソッドを子クラスで書いてオーバーライドしたつもりになっても、
それは親クラスのメソッドとは全く別の関数として認識される。

#include <stdio.h>
class CParent{
    public:
        void parent_method(){printf("i am parent.");}
};
class CChild :public CParent{
 
}
void main(){
    CChild c;
    c.parent_method();
}

出力結果

i am parent.

関数の引数に親クラスの名前を書くと子クラスも引数にしてもいい

class Child:public Parent{};
void method(Parent& _p){}
void main(){
 Child c;
    method(c);//これはコンパイルが通る
}

サブクラスのメンバ変数名について

親クラスで宣言されたメンバ変数があるとする。
全く同じ名前の変数を子クラスでつけたら、それは全く違う変数として扱われるのに注意。
なので、どう頑張っても、せっかく作った親クラスの変数を呼び出せなくなるってこと。
class ChildClass : public ParentClass{
public: 
int member;
};

サブクラスでのメソッドオーバーライド

オーバーロードしたいなら親クラスの関数にvirtualをつけて仮想関数にする。

void ParentClass::Method(){}

たとえ同じ名前の関数を作ったとしても、中身で親を呼び出さないと、親クラスとは全く無関係のクラスになっちゃうよ。
void ChildClass::Method(){
ParentClass::Method();
}

この手法は、
親クラスのある関数を完全にオーバーライドせずに、代わりにちょっとした機能を追加したい場合に使う[6]。

親クラスと同じ名前の変数

JavaでもC++でも同じ挙動である。
デバッガで見ると、親クラスの変数の領域もちゃんと確保されていて、その中にデータも入っている。
しかし、親クラスの同じ名前の変数へアクセスする方法はなくなる。
つまり、アクセス出来ない開かずの倉庫が出来てしまうようなかんじなのだ。

samename.png
eclipse.png
上の図はC++ in Visual Studioで見た場合。
下の図はJAva in EclipseでWatchした場合
ホーマーの好きな食べ物はドーナツ。
バートの好きな食べ物はチューイングガム。
ホーマーの好きな食べ物がドーナツだって情報もしっかりメモリ領域に残っている。
しかし、その情報には決してアクセスすることは出来ない。。。!!親クラスで何かpublicな関数によって
情報提供されていない限り!

継承したときのコンストラクタについて

なにもしなかった場合

  1. まず親クラスのデフォルトコンストラクタが呼ばれ、
  2. そのあと子クラスの然るべきコンストラクタが呼ばれる。

JavaでもC++でも同じ挙動をする

明示的に呼ぶ親クラスのコンストラクタを指定する。

コンストラクタ名(…) : 基底クラスコンストラクタ名(…);

Child(int a) : Parent(a)//別に同じ引数じゃなくてもいい
  {  }

つまり、デフォルト状態ではこうなってるってこと
Child(int a) : Parent()
  {  }

ちゃんとやらないと、C2664エラーになる時がある

サポートサイト Wikidot.com