1. 程式人生 > >C++筆記 第五十三課 被遺棄的多重繼承(上)---狄泰學院

C++筆記 第五十三課 被遺棄的多重繼承(上)---狄泰學院

如果在閱讀過程中發現有錯誤,望評論指正,希望大家一起學習,一起進步。
學習C++編譯環境:Linux

第五十三課 被遺棄的多重繼承(上)

1.問題

C++中是否允許一個類繼承自多個父類?允許

2.C++支援編寫多重繼承的程式碼

一個子類可以擁有多個父類
子類擁有父類的成員變數

子類繼承所有父類的成員函式
子類物件可以當做任意父類物件使用
多重繼承的語法規則
在這裡插入圖片描述
多重繼承的本質與單繼承相同!

53-1 多重繼承問題一

#include <iostream>
#include <string>
using namespace std;
class BaseA
{
    int ma;
public:
    BaseA(int a)
    {
	ma = a;
    }
    int getA()
    {
	return ma;
    }
};
class BaseB
{
    int mb;
public:
    BaseB(int b)
    {
	mb = b;
    }
    int getB()
    {
	return mb;
    }
};
class Derived : public BaseA, public BaseB
{
    int mc;
public:
    Derived(int a, int b, int c) :BaseA(a), BaseB(b)
    {
	mc = c;
    }
    int getC()
    {
	return mc;
    }
    void print()
    {
	cout << "ma =" << getA() << ","
             << "mb =" << getB() << ","
	     << "mc =" << mc << endl;
    }
};
int main()
{
   cout << "sizeof(Derived) = " << sizeof(Derived) << endl; //12
   
    Derived d(1,2,3);
    d.print();
    cout << "d.getA() = " << d.getA() << endl;
    cout << "d.getB() = " << d.getB() << endl;
    cout << "d.getC() = " << d.getC() << endl;
    cout << endl;
    BaseA* pa = &d;
    BaseB* pb = &d;
    cout << "pa->getA() = " << pa->getA() << endl;
    cout << "pb->getB() = " << pb->getB() << endl;
    cout << endl;
    void* paa = pa;
    void* pbb = pb;
    if( paa == pbb)
    {
	cout << "Pointer to the same object!" << endl;
    }
    else
    {
	cout << "Error" << endl;
    }
    cout << "pa = " << pa << endl;
    cout << "pb = " << pb << endl;
    cout << "paa = " << paa << endl;
    cout << "pbb = " << pbb << endl;
    return 0;
}
執行結果
sizeof(Derived) = 12
ma =1,mb =2,mc =3
d.getA() = 1
d.getB() = 2
d.getC() = 3
pa->getA() = 1
pb->getB() = 2
Error
pa = 0x7fffe245f4b0
pb = 0x7fffe245f4b4
paa = 0x7fffe245f4b0
pbb = 0x7fffe245f4b4

3.多重繼承問題一

通過多重繼承得到的物件可能擁有“不同的地址”!!
解決方案:無
實質:指向同一個物件的不同位置(一個指向頭,一個指向腿)
在這裡插入圖片描述

4.多重繼承的問題二

多重繼承可能產生冗餘的成員
在這裡插入圖片描述

53-2 多重繼承問題二

#include <iostream>
#include <string>
using namespace std;
class People
{
    string m_name;
    int m_age;
public:
    People(string name, int age)
    {
	m_name = name;
	m_age = age;
    }
    void print()
    {
	cout << "Name = " << m_name << ","
	     << "Age = " << m_age << endl;
    }
};
class Teacher : virtual public People
{
public:
    Teacher(string name, int age) : People(name, age)
    {
    }
};
class Student : virtual public People
{
public:
    Student(string name, int age) : People(name, age)
    {
    }
};
class Doctor : public Teacher, public Student
{
public:
    Doctor(string name, int age) : Teacher(name + "1", age + 1), Student(name, age),People(name, age)
{
}
};
int main()
{
    Doctor d("Delphi", 33);
    //d.print();
    d.Teacher::print();
    d.Student::print();
    
    return 0;
}
執行結果
Name = Delphi,Age = 33
Name = Delphi,Age = 33

無論執行哪種方式,兩者結果是一樣的。
當多重繼承關係出現閉合時將產生資料冗餘的問題!!!
解決方案:虛繼承
在這裡插入圖片描述
虛繼承能夠解決資料冗餘問題
中間層父類不再關係頂層父類的初始化
最終子類必須直接呼叫頂層父類的建構函式
問題:當架構設計中需要繼承時,無法確定使用直接繼承還是虛繼承!!!
犧牲效率,犧牲移植性,架構師不喜歡多繼承,多重繼承僅作學術研究。
小結
C++支援多重繼承的程式設計方式
多重繼承容易帶來問題
可能出現“同一個物件的地址不同”的情況
虛繼承可以解決資料冗餘的問題
虛繼承的使得架構設計可能出現問題