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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

【C++深度剖析教程31】被遗弃的多重继承

發(fā)布時間:2023/12/10 c/c++ 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C++深度剖析教程31】被遗弃的多重继承 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

加qq1126137994 微信:liu1126137994

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

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

  • 一個子類可以擁有多個父類
  • 子類擁有所有父類的成員變量
  • 子類繼承父類所有的成員函數(shù)
  • 子類對象可以當(dāng)做任意父類對象使用

多重繼承的語法規(guī)則:

多重繼承的本質(zhì)與單繼承相同

編程示例;

#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; }

運(yùn)行結(jié)果:

分析以上程序我們就可以發(fā)現(xiàn)問題所在啦:
1、通過多重繼承的對象可能擁有不同的地址

2、多重繼承可能產(chǎn)生冗余的成員:

當(dāng)多重繼承關(guān)系閉合將產(chǎn)生數(shù)據(jù)冗余問題
解決辦法是:
虛繼承!!!

下面看一個解決冗余的例子:

#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; }

運(yùn)行結(jié)果為;
Name = Delphi, Age = 33

  • 虛繼承能夠解決數(shù)據(jù)冗余的問題
  • 中間層父類不再關(guān)心頂層父類的初始化
  • 最終子類必須直接調(diào)用頂層父類的構(gòu)造函數(shù)
  • 雖然我們解決的數(shù)據(jù)冗余,但是還有一個問題,在架構(gòu)設(shè)計師,無法確定使用虛繼承還是直接繼承???

    3、多重繼承有可能會產(chǎn)生多個虛函數(shù)表

    #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); //dynamic_cast會對指針進(jìn)行修正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; }

    工程開發(fā)中的多繼承方式:

    #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; }

    運(yùn)行結(jié)果:

    p->getI() = 100
    p->getI() = 40

    pInt1 == p : 1
    pInt2 == p : 1

    一些有用的工程建議:

  • 先繼承自一個父類,然后實(shí)現(xiàn)多個接口
  • 父類中提供equal()成員函數(shù)
  • equal()成員函數(shù)用于判斷當(dāng)前指針是否指向當(dāng)前對象
  • 與多重繼承相關(guān)的強(qiáng)制類型轉(zhuǎn)換用dynamic_cast完成
  • 總結(jié):

  • 多繼承中可能出現(xiàn)多個虛函數(shù)表指針
  • 與多重繼承相關(guān)的強(qiáng)制類型轉(zhuǎn)換用dynamic_cast完成
  • 工程開發(fā)中使用單繼承多接口的方式實(shí)現(xiàn)多繼承
  • 父類提供成員函數(shù)用來判斷指針是否指向當(dāng)前對象
  • 總結(jié)

    以上是生活随笔為你收集整理的【C++深度剖析教程31】被遗弃的多重继承的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。