先看這個:
class base
{
public:
int b;
void print() {cout 《 "base" 《 endl;}
};
class derived1 : public base
{
public:
int d1;
};
class derived2 : public base
{
public:
int d2;
};
class grandson : public derived1,public derived2
{
public:
int g;
};
這里,我們讓derived1和derived2繼承base,再讓grandson繼承derived1和derived2,我們是想實現(xiàn)一個菱形結(jié)構(gòu):
我們可以寫出主程序:
void main()
{
grandson gs;
// gs.b = 1;
// gs.base::b = 1;
// gs.print();
}
看見我加注釋的那三句話了嗎?每句都會報錯的!為什么那?
因為,想實現(xiàn)棱形結(jié)構(gòu)只是我們的一廂情愿!我們又沒告訴編譯器,編譯器哪有那么聰明!
實際結(jié)構(gòu)是這樣的:
所以我們應該這樣寫main函數(shù):
void main()
{
grandson gs;
gs.derived1::b = 1;
gs.derived2::b = 1;
gs.derived1::print();
gs.derived2::print();
}
可以看到,從基類base繼承來的成員b和print()函數(shù)在grandson中都有兩份,這可不是我們想要的!因為這兩個b是一樣的,都是從base來的;print()也是!
其實,這個問題很好解決,科學家發(fā)明了關(guān)鍵字virtual來解決這個問題:
class base
{
public:
int b;
void print(){cout 《 "base" 《 endl;}
};
class derived1 : virtual public base
{
public:
int d1;
};
class derived2 : virtual public base
{
public:
int d2;
};
class grandson : public derived1,public derived2
{
public:
int g;
};
現(xiàn)在我們可以這樣寫主函數(shù)了:
void main()
{
grandson gs;
gs.b = 1;
gs.base::b = 1;
// gs.derived1::b = 1;
// gs.derived2::b = 1;
gs.print();
// gs.derived1::print();
// gs.derived2::print();
}
現(xiàn)在,grandson的b和print都只有一份了,所以編譯器不會再告訴我們“ambiguous”了!
當然,按我加注釋那幾句那么寫也沒問題,反正現(xiàn)在b和print()都是各占一份內(nèi)存空間,不再分derived1和derived2繼承過來的,是從他們兩個共同從base繼承過來的。
請注意,對于base,我們什么也沒做,他現(xiàn)在就叫做虛基類,因為derived1和derived2在繼承時加了關(guān)鍵字virtual!
在現(xiàn)實世界中這種情況是很多見的,比如公司的臨時銷售人員,又有銷售人員的屬性,也有臨時人員的屬性;還有中國老師上課常用的老師和研究生派生的助教的例子,等等。
總之,你只要記?。寒斈阆雽崿F(xiàn)棱形結(jié)構(gòu)時,請使用virtual!
凡本站注明“稿件來源:新科教育”的所有圖文音視頻,版權(quán)均屬新科所有,任何媒體、網(wǎng)站或個人未經(jīng)本網(wǎng)協(xié)議授權(quán)不得轉(zhuǎn)或以其他方式復制發(fā)表。已獲得本站協(xié)議
授權(quán)的媒體、網(wǎng)站,在下載使用時必須注明“稿件來源:新科教育”,違者本站將依法追究責任。