C++虛繼承簡單講解

多繼承及潛在問題

對象的繼承,指的是一個子類對象獲得父類對象的所有屬性和方法,並且可以在此基礎上拓展新的屬性和方法的一種行爲(個人理解,請勿當真。。)

那麼繼承可以一直進行,比如c繼承自b,b又繼承自a,那麼c的父類是b,b的父類是a,c的爺類是a,這好理解

但是值得注意的是,c++可以支持多繼承
這意味着

  1. 一個類可以有多個爹(父類)
  2. 爹類(父類)們,可能擁有共同的父類
  3. 那麼一個類可能會擁有多個爺類,這時候就會發生衝突,因爲爺類是同一個(即如下圖的a)

在這裏插入圖片描述
這個時候就會發生問題,因爲繼承的特性是:子類先創建父類的對象,在創建子類自己的屬性,那麼會創建兩個爺類對象,可是實際生產生活中一般只用一個爺類對象就夠了,這可能有些抽象,所以舉個例子:

  1. 有一個animal動物類,animal類有age年齡屬性
  2. cat類和dog類繼承自animal類
  3. 出現了新物種:catdog,catdog類繼承自cat類和dog類(多繼承)

按照繼承特性,繼承自cat和dog,cat和dog都會創建一個animal對象,所以catdog類有兩個animal對象,那麼catdog擁有兩個年齡屬性

可是客觀描述和實際編程,年齡都是唯一的變量,這就造成了衝突和客觀描述上的矛盾,而且造成了不必要的內存開銷

更致命的是,同名的age變量更容易造成衝突與bug

如下的代碼揭示了這種不合理的情況(即創建兩個animal對象)
在這裏插入圖片描述

#include <bits/stdc++.h>

using namespace std;

class animal
{
public:
	int age;
	animal(){cout<<"animal對象被創建"<<endl;}
};

class cat : public animal
{
public:
	int c;
	cat(){cout<<"cat對象被創建"<<endl;}	
};

class dog : public animal
{
public:
	int d;
	dog(){cout<<"dog對象被創建"<<endl;}	
};

class catdog : public cat, public dog
{
public:
	int cd;
	catdog(){cout<<"catdog對象被創建"<<endl;}
};

int main()
{ 	
	catdog cd;
	
	return 0;
}

解決方案:虛繼承

因爲繼承的特性,子類在創建的時候,會先創建父類,所以上述問題會有兩個爺類的情況出現,而我們需要消滅一個爺

虛擬繼承的解決方法,是使得多繼承的時候,某個公共基類的成員在其派生類(子類)中只產生一個拷貝

實現方法:virtual關鍵字

cat類和dog類在繼承基類animal的時候,加上virtual關鍵字,就會使得在後續的多繼承中,如果catdog類的父類cat和dog都繼承自animal,那麼只會產生一個animal對象而不是兩個

在這裏插入圖片描述

代碼

#include <bits/stdc++.h>

using namespace std;

class animal
{
public:
	int age;
	animal(){cout<<"animal對象被創建"<<endl;}
};

// 繼承基類時加上 virtual 關鍵字
class cat : virtual public animal
{
public:
	int c;
	cat(){cout<<"cat對象被創建"<<endl;}	
};

// 繼承基類時加上 virtual 關鍵字
class dog : virtual public animal
{
public:
	int d;
	dog(){cout<<"dog對象被創建"<<endl;}	
};

class catdog : public cat, public dog
{
public:
	int cd;
	catdog(){cout<<"catdog對象被創建"<<endl;}
};

int main()
{ 	
	catdog cd;
	
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章