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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多重继承与虚继承编程实验

發布時間:2024/4/18 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多重继承与虚继承编程实验 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

多重繼承與虛繼承編程實驗

    • 基本知識
      • 多重繼承
      • 多重繼承下的類作用域
      • 虛繼承
      • 構造函數與虛繼承
      • 關于本程序
    • 示例代碼
      • Animal_virtual_baseVers.h
      • virt-inherit.cpp
      • 運行結果

本文是本人大一期間在校學習C++課程時所撰寫的實驗報告的摘錄,由于剛上大學,剛接觸計算機編程方面的相關知識,故可能會有很多不足甚至錯誤的地方,還請各位看官指出及糾正。
本文所涉及到的“教材”指:
電子工業出版社《C++ Primary中文版(第5版)》
如需轉載或引用請標明出處。

基本知識

多重繼承

多重繼承在概念上比較簡單,即指從多個直接基類中產生派生類的能力,多重繼承的派生類繼承了所有父類的屬性。例如:

class Panda : public Bear, public Raccoon, public Endangered { /**/ }

每個基類包含一個可選的訪問說明符,且多重繼承的派生列表也只能包含已經被定義的非final類,同一個基類只能在一個派生列表中出現一次。

在多重繼承關系中,派生類的對象包含有每個基類的子對象。構造一個派生類的對象將同時構造并初始化它的所有基類子對象,且它的構造函數初始值也只能初始化它的直接基類。派生的構造函數初始值列表將實參分別傳遞給每個直接基類,其中基類的構造順序與派生類表中基類的出現順序保持一致(例如本次實驗程序中的Panda類的構造函數)。

多重繼承下的類作用域

在只有一個基類的情況下,派生類的作用域嵌套在直接基類和間接基類的作用域中,查找過程沿著繼承體系自底向上進行,直到找到所需的名字。派生類的名字將隱藏基類的同名成員

在多重繼承的情況下,相同的查找過程在所有直接基類中同時進行。如果名字在多個基類中都被找到,則對該名字不加前綴限定符的直接使用將具有二義性。例如,如果有Zoo類和Endangered類都定義了名為aa的函數,并且同時繼承這兩個類的Panda類沒有定義該成員,則下面的調用是錯誤的:

Panda lie; lie.aa();

為了避免產生二義性的調用,我們可以在每次調用時都指出所調用的版本(如lie.Zoo::aa())或者在Panda類中定義屬于自己版本的aa函數。

虛繼承

雖然在一個派生列表中一個基類只能出現一次,但在一個派生過程中可以多次繼承同一個類,例如派生了可以通過它多個直接基類分別繼承同一個間接基類,也可以直接繼承某個基類,然后通過另一個基類再一次間接繼承該類。如果某個類自派生過程中出現了多次,則派生類中將包含該類的多個子對象。在C++中,可以通過虛繼承的機制解決重復繼承某個類可能產生的一些問題。

虛繼承的目的是令某個類做出聲明,承諾愿意共享它的基類。其中,共享的基類子對象成為虛基類。在這種機制下,不論虛基類在繼承體系中出現了多少次,在派生類中都只包含唯一一個共享的虛基類子對象。下面是一個虛繼承的例子:

class Raccoon :public virtual ZooAnimal { /*...*/ }; class Bear :public virtual ZooAnimal { /*...*/ }; class Panda : public Bear, public Raccoon { /*...*/ };

指定虛基類的方式是在派生列表中添加關鍵字virtual,上面的代碼說明將ZooAnimal定義為Raccoon和Bear的虛基類。Panda通過Raccoon和Bear繼承了ZooAnimal,因為Raccoon和Bear繼承ZooAnimal的方式都是虛繼承,所以在Panda中只有一個ZooAnimal基類部分。

構造函數與虛繼承

在虛派生中,虛基類由最低層的派生類初始化。如在本次實驗的程序中,當創建Panda對象時,由Panda的構造函數獨立控制ZooAnimal的初始化過程。含有虛基類的對象的構造順序為:首先使用提供給最低層派生類構造函數的初始值初始化該對象的虛基類子部分,接下來按照直接基類在派生列表中出現的次序依次對其進行初始化。例如在上面的例子中,當我們創建一個Panda對象時,首先使用Panda的構造函數初始化列表中提供的初始值構造虛基類ZooAnimal部分,接下來構造Bear部分,然后構造Raccoon部分,最后狗仔Panda部分。Pan對象的銷毀順序與其構造順序相反。

關于本程序

該程序定義了多個不同的類,它們之間有著多重繼承或虛繼承的關系。通過對這些類的對象的成員訪問,展示多重繼承及虛繼承的原理和特點。

詳見代碼注釋部分

示例代碼

Animal_virtual_baseVers.h

#include <string> #include <iostream> class Endangered //用于當作輔助類的類Panda的直接基類Endangered { public:enum Status { critical, environment, improving }; //枚舉類型成員Endangered(Status stat = improving): animal_status(stat) { } //構造函數,形參stat有默認值virtual ~Endangered() //Endangered的析構函數{ std::cout << "Endangered::~Endangered" << std::endl; }virtual std::ostream& print(std::ostream&) const //Endangered的print函數{ return std::cout << "Endangered::print" << std::endl; }virtual void highlight() const //Endangered的highlight函數{ std::cout << "Endangered::highlighted" << std::endl; }// . . . private:Status animal_status; //唯一的私有成員 };class ZooAnimal; //類聲明 extern std::ostream& operator<<(std::ostream&, const ZooAnimal&); //該函數定義在別的文件中class ZooAnimal //類Panda的間接基類ZooAnimal,被Raccoon類及Bear類虛繼承 { public:ZooAnimal(): exhibit_stat(false) { } //默認構造函數:把exhibit_stat設為falseZooAnimal(std::string animal, bool exhibit, std::string family): nm(animal), exhibit_stat(exhibit), fam_name(family) { } //接受參數的構造函數virtual ~ZooAnimal() { std::cout << "ZooAnimal::~ZooAnimal" << std::endl; } //虛函數:ZooAnimal的析構函數virtual std::ostream& print(std::ostream&) const //虛函數:ZooAnimal的print函數{ return std::cout << "ZooAnimal::print" << std::endl; }virtual int population() const //虛函數:ZooAnimal的population函數{std::cout << "ZooAnimal::population" << std::endl; return 0;}//下面是用于訪問成員的函數std::string name() const { return nm; }std::string family_name() const { return fam_name; }bool onExhibit() const { return exhibit_stat; }// . . . protected:std::string nm; bool exhibit_stat; std::string fam_name;// . . . private: };//下面兩個類的關鍵字public和virtual的順序沒有要求 class Raccoon : public virtual ZooAnimal //類Panda的直接基類Raccoon,虛繼承類ZooAnimal { public:Raccoon(): pettable_flag(false) { } //默認構造函數:把pettable_flag設為falseRaccoon(std::string name, bool onExhibit=true); //接受參數的構造函數virtual std::ostream& print(std::ostream&) const //虛函數:Raccoon的print函數{ return std::cout << "Raccoon::print" << std::endl; }bool pettable() const { return pettable_flag; } //成員函數:返回pettable_flagvoid pettable(bool petval) { pettable_flag = petval; } //成員函數:改變pettable_flag的值// . . .protected: bool pettable_flag; //bool類型的成員:pettable_flag // . . . };class Bear : virtual public ZooAnimal //類Panda的直接基類Bear,虛繼承類ZooAnimal { public://當Bear是最底層的派生類時,將會把"Bear"給ZooAnimal的構造函數Bear(std::string name, bool onExhibit=true); protected:Bear() : dance_flag(two_left_feet) { } //默認構造函數:把dance_flag設為two_left_feetpublic:enum DanceType { two_left_feet, macarena, fandango }; //枚舉類型成員:指示熊跳的舞種virtual std::ostream &print(std::ostream&) const //虛函數:Bear的print函數{ return std::cout << "Bear::print" << std::endl; }virtual std::string isA() const //虛函數:Bear的isA函數{ std::cout << "Bear::isA" << std::endl; return "Bear"; }int mumble(int) //Bear的成員函數mumble{ std::cout << "Bear::mumble" << std::endl; return 0; } void dance(DanceType) const //Bear的成員函數dance { std::cout << "Bear::dance" << std::endl; }virtual ~Bear() { std::cout << "Bear::~Bear" << std::endl; } //虛函數:Bear的析構函數 private:std::string name;DanceType dance_flag; };//Panda類多重繼承三個類Bear、Raccoon以及Endangered class Panda : public Bear, public Raccoon, public Endangered { public:Panda(): sleeping_flag(false) { } //默認構造函數:把sleeping_flag設為falsePanda(std::string name, bool onExhibit=true); //接收參數的構造函數,其中形參onExhibit有默認值virtual std::ostream& print(std::ostream&) const //虛函數:Panda的print函數{ return std::cout << "Panda::print" << std::endl; }bool sleeping() const { return sleeping_flag; } //成員函數:返回sleeping_flagvoid sleeping(bool newval) { sleeping_flag = newval; } //成員函數:改變sleeping_flag的值// . . .protected:bool sleeping_flag;// . . . };Bear::Bear(std::string name, bool onExhibit) : ZooAnimal(name, onExhibit, "Bear") { } Raccoon::Raccoon(std::string name, bool onExhibit) : ZooAnimal(name, onExhibit, "Raccoon"), pettable_flag(false) { } //由于Bear和Raccoon共同虛繼承ZooAnimal,所以Panda中只有一個ZooAnimal基類部分 //即此構造函數的結果,是一個Panda對象, //內部ZooAnimal基類部分、Bear特有的部分、Raccoon特有的部分、Endangered的部分以及Panda自己特有的部分各有一份 Panda::Panda(std::string name, bool onExhibit): ZooAnimal(name, onExhibit, "Panda"), Bear(name, onExhibit), Raccoon(name, onExhibit), Endangered(Endangered::critical), sleeping_flag(false) { }

virt-inherit.cpp

#include "Animal_virtual_baseVers.h" #include <iostream> using std::cout; using std::endl; using std::ostream;//下面這三個函數用于測試多重繼承及虛繼承的特點 //dance要求傳入一個Bear類的引用 void dance(const Bear&) { cout << "dance(const Bear&)" << endl; } //rummage要求傳入一個Raccoon類的引用 void rummage(const Raccoon&) { cout << "rummage(const Raccoon&)" << endl; } //重載的<<運算符要求傳入一個ZooAnimal類的引用 ostream& operator<<(ostream&, const ZooAnimal&) { return cout << "ZooAnimal output operator" << endl; }int main (void) {Panda ying_yang;dance(ying_yang); //將Panda對象當作Bear對象傳遞是對的rummage(ying_yang); //將Panda對象當作Raccoon對象傳遞是對的cout << ying_yang; //將Panda對象當作ZooAnimal對象傳遞是對的//-----下面是新增的測試部分-----//putchar('\n');ying_yang.isA(); //調用Panda自己的成員函數ying_yang.highlight(); //調用Endangered類部分的成員函數//下面四個函數調用說明多重繼承潛在的的二義性問題 ying_yang.print(cout); //由于Panda有定義自己的print函數,故這樣調用沒有二義性ying_yang.Bear::print(cout); //可以通過指出print的版本,避免產生二義性ying_yang.Raccoon::print(cout);ying_yang.ZooAnimal::print(cout);//------新增的測試部分結束------//system("pause");return 0; }

運行結果

總結

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

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