日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++中的多重继承

發布時間:2025/4/5 c/c++ 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++中的多重继承 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 1 C++中的多重繼承
    • 2 C++中多重繼承帶來的問題
      • 2.1 同一個對象的地址不同
      • 2.2 帶來數據冗余的問題
      • 2.3 可能產生多個虛函數表
    • 3 工程開發中多重繼承的方式

1 C++中的多重繼承

C++支持編寫多重繼承的代碼:

  • 一個子類可以擁有多個父類。
  • 子類擁有所有父類的成員變量。
  • 子類繼承所有父類的成員函數。
  • 子類對象可以當作任意父類對象使用。

多重繼承的語法規則:

多繼承的構造函數的調用順序:

  • 父類構造函數的調用順序和和它們在子類構造函數中出現的順序無關,而是和聲明子類時父類出現的順序相同。

2 C++中多重繼承帶來的問題

2.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; // 12Derived 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; }

執行結果如下:

問題分析:

2.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 : public People { public:Teacher(string name, int age) : People(name, age){} };class Student : 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), Student(name + "2", age){} };int main() {Doctor d("Delphi", 33);//d.print(); // 編譯error,因為成員函數冗余,編譯器不知道調用哪個d.Teacher::print();d.Student::print();return 0; }

打印結果:

當多重繼承關系出現閉合時將產生數據冗余的問題!

解決方案:虛繼承

對于虛繼承:

  • 虛繼承能夠解決數據冗余的問題。
  • 中間層父類不再關心頂層父類的初始化。
  • 最終子類必須直接調用頂層父類的構造函數。

上面那個被共享的基類(People)就稱為虛基類(Virtual Base Class)。

解決方案代碼:

#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, age), Student(name, age), People(name, age){} };int main() {Doctor d("Delphi", 33);d.print();return 0; }

在架構設計中需要繼承時,我們是無法確定使用直接繼承還是虛繼承!虛繼承會使得架構設計可能出現問題。

2.3 可能產生多個虛函數表

多重繼承可能產生多個虛函數表:

示例代碼如下:

#include <iostream> #include <string>using namespace std;class BaseA { public:virtual void funcA(){cout << "BaseA::funcA()" << endl;} };class BaseB { public:virtual void funcB(){cout << "BaseB::funcB()" << endl;} };class Derived : public BaseA, public BaseB {};int main() {Derived d;BaseA* pa = &d;BaseB* pb = &d;BaseB* pbb = (BaseB*)pa; // oops!!cout << "sizeof(d) = " << sizeof(d) << endl;cout << "Using pa to call funcA()..." << endl;pa->funcA();cout << "Using pb to call funcB()..." << endl;pb->funcB();cout << "Using pbc to call funcB()..." << endl;pbb->funcB();cout << endl;return 0; }

輸出結果如下:


修改后的代碼:

#include <iostream> #include <string>using namespace std;class BaseA { public:virtual void funcA(){cout << "BaseA::funcA()" << endl;} };class BaseB { public:virtual void funcB(){cout << "BaseB::funcB()" << endl;} };class Derived : public BaseA, public BaseB {};int main() {Derived d;BaseA* pa = &d;BaseB* pb = &d;BaseB* pbe = (BaseB*)pa; // oops!!BaseB* pbc = dynamic_cast<BaseB*>(pa);cout << "sizeof(d) = " << sizeof(d) << endl;cout << "Using pa to call funcA()..." << endl;pa->funcA();cout << "Using pb to call funcB()..." << endl;pb->funcB();cout << "Using pbc to call funcB()..." << endl;pbc->funcB();cout << endl;cout << "pa = " << pa << endl;cout << "pb = " << pb << endl;cout << "pbe = " << pbe << endl;cout << "pbc = " << pbc << endl;return 0; }

輸出結果:


3 工程開發中多重繼承的方式

工程中我們使用如下“單繼承多接口”的方式使用多重繼承:

對于正確的使用多重繼承,一些有用的工程建議:

  • 先繼承自一個父類,然后實現多個接口。
  • 父類中提供equal()成員函數。
  • equal()成員函數用于判斷指針是否指向當前對象。
  • 與多重繼承相關的強制類型轉換用dynamic_cast完成。

示例代碼:

#include <iostream> #include <string>using namespace std;class Base { protected:int mi; public:Base(int i){mi = i;}int getI(){return mi;}bool equal(Base* obj){return (this == obj);} };class Interface1 { public:virtual void add(int i) = 0;virtual void minus(int i) = 0; };class Interface2 { public:virtual void multiply(int i) = 0;virtual void divide(int i) = 0; };class Derived : public Base, public Interface1, public Interface2 { public:Derived(int i) : Base(i){}void add(int i){mi += i;}void minus(int i){mi -= i;}void multiply(int i){mi *= i;}void divide(int i){if( i != 0 ){mi /= i;}} };int main() {Derived d(100);Derived* p = &d;Interface1* pInt1 = &d;Interface2* pInt2 = &d;cout << "p->getI() = " << p->getI() << endl; // 100pInt1->add(10);pInt2->divide(11);pInt1->minus(5);pInt2->multiply(8);cout << "p->getI() = " << p->getI() << endl; // 40cout << endl;cout << "pInt1 == p : " << p->equal(dynamic_cast<Base*>(pInt1)) << endl;cout << "pInt2 == p : " << p->equal(dynamic_cast<Base*>(pInt2)) << endl;return 0; }

參考資料:

  • C++深度解析教程
  • C/C++從入門到精通-高級程序員之路【奇牛學院】
  • 總結

    以上是生活随笔為你收集整理的C++中的多重继承的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。