読者です 読者をやめる 読者になる 読者になる

Awesome Hacks!

プログラミング初心者なので地道に勉強していきます。分からない人の立場から整理していきます。

クラスの基本_多重継承

複数のクラスから継承

余計なことは言わない、というより言うべきでないし、言う必要もない。
クラスAからもクラスBからも継承したいから、一気に継承してしまえという話。


 
つまり、継承時に

class C : public A, public B {

とするだけ。

加えて、派生クラスから
 
【プログラム例】

#include <iostream>
using namespace std;

class Father {
    public:
        void fatherMes(){
            cout << "FatherのoutMes" << endl;
        }
        void sameName(){
            cout << "FatherのsameName" << endl;
        }
};

class Mother {
    public:
        void motherMes(){
            cout << "MotherのoutMes" << endl;
        }
        void sameName(){
            cout << "MotherのsameName" << endl;
        }
};

class Child : public Father, public Mother {
    public:
        void childMes(){
            cout << "ChildのoutMes" << endl;
        }
        void sameName(){
            cout << "ChildのsameName" << endl;
        }
};

int main(){
    Child c;

    c.fatherMes();
    c.motherMes();
    c.childMes();

    c.Father::sameName();
    c.Mother::sameName();
    c.Child::sameName();
   
    return 0;
}


【実行結果】

$
FatherのoutMes
MotherのoutMes
ChildのoutMes
FatherのsameName
MotherのsameName
ChildのsameName
$



自分はここであることに気づく。
 
仮想関数にしなくても派生クラスのオブジェクトで基本クラスの関数が呼べるみたい。
 
 
また、多重継承では仮想関数も有効のようだ。
 
【プログラム例】

#include <iostream>
using namespace std;

class Father {
	public:
		void sameName(){
			cout << "FatherのsameName" << endl;
		}
		virtual void virtualName(){
			cout << "FatherのvirtualName" << endl;
		}
};

class Mother {
	public:
		void sameName(){
			cout << "MotherのsameName" << endl;
		}
};

class Child : public Father, public Mother {
	public:
		void sameName(){
			cout << "ChildのsameName" << endl;
		}
		void virtualName(){
			cout << "ChildのvirtualName" << endl;
		}
};

int main(){
	Father *p;
	Child c;
	p = &c;

	p->Father::sameName();
	p->sameName();				// 基本クラスのポインタなので基本クラスの関数が呼ばれる
//	p->Child::sameName();		// 当然基本クラスのポインタなのでコンパイルエラー
	p->virtualName();			// 多重継承でも仮想関数は有効
//	p->Child::virtualName();	// コンパイルエラー

	// 上記の通り、仮想関数か否かを問わず、基本クラスのポインタが指す
	// 派生クラスのオブジェクトの関数を「Child::」のように
	// 呼び出すことはできない。
	
	return 0;
}

  
【実行結果】

$
FatherのsameName
FatherのsameName
ChildのvirtualName
$

 
 
もちろん、基本クラスのオブジェクトから派生クラスの関数は呼べない様子。
【プログラム例】

#include <iostream>
using namespace std;

class Father {
	public:
		void fatherMes(){
			cout << "FatherのoutMes" << endl;
		}
		void sameName(){
			cout << "FatherのsameName" << endl;
		}
};

class Mother {
	public:
		void motherMes(){
			cout << "MotherのoutMes" << endl;
		}
		void sameName(){
			cout << "MotherのsameName" << endl;
		}
};

class Child : public Father, public Mother {
	public:
		void childMes(){
			cout << "ChildのoutMes" << endl;
		}
		void sameName(){
			cout << "ChildのsameName" << endl;
		}
};

int main(){
	Father f;

	f.Mother::motherMes();
	f.Child::childMes();

	f.Mother::sameName();
	f.Child::sameName();
	
	return 0;
}


【実行結果】

$
testManyDerive2.cpp:37:12: error: 'Mother::motherMes' is not a member of class 'Father'
        f.Mother::motherMes();
          ~~~~~~~~^
testManyDerive2.cpp:38:11: error: 'Child::childMes' is not a member of class 'Father'
        f.Child::childMes();
          ~~~~~~~^
testManyDerive2.cpp:40:12: error: 'Mother::sameName' is not a member of class 'Father'
        f.Mother::sameName();
          ~~~~~~~~^
testManyDerive2.cpp:41:11: error: 'Child::sameName' is not a member of class 'Father'
        f.Child::sameName();
          ~~~~~~~^
4 errors generated.
$


 

クラスの階層化 ー 派生クラスの派生クラス

派生クラスからさらに派生したクラスの挙動については、個人的に緊急性がないというべきか、重要度が高くないので割愛する。