成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

C++進(jìn)階繼承-創(chuàng)新互聯(lián)

作者:@小萌新
專(zhuān)欄:@C++進(jìn)階
作者簡(jiǎn)介:大二學(xué)生 希望能和大家一起進(jìn)步!
本篇博客簡(jiǎn)介:簡(jiǎn)單介紹C++中繼承的概念

成都創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:做網(wǎng)站、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿(mǎn)足客戶(hù)于互聯(lián)網(wǎng)時(shí)代的太平網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

繼承
  • 繼承的概念及定義
    • 繼承的概念
  • 繼承的定義
    • 定義格式
    • 繼承方式和訪(fǎng)問(wèn)限定符
    • 默認(rèn)繼承方式
  • 基類(lèi)和派生類(lèi)的賦值轉(zhuǎn)換
  • 繼承中的作用域
  • 派生類(lèi)的默認(rèn)成員函數(shù)
  • 繼承與友元
  • 繼承與靜態(tài)成員
  • 繼承方式
    • 單繼承
    • 多繼承
    • 菱形繼承
    • 菱形的虛擬繼承
    • 菱形虛擬繼承的原理
    • 繼承與組合
  • 筆試面試題
  • 總結(jié)

繼承的概念及定義 繼承的概念

繼承是一種面向?qū)ο缶幊痰母拍?,它指的是一個(gè)類(lèi)(稱(chēng)為子類(lèi))可以從另一個(gè)類(lèi)(稱(chēng)為父類(lèi))中繼承屬性和方法。這意味著子類(lèi)可以獲得父類(lèi)中定義的所有屬性和方法,并且可以在不改變父類(lèi)代碼的情況下擴(kuò)展或修改這些屬性和方法。

那么這么做的優(yōu)點(diǎn)是什么呢?

很顯然的一點(diǎn) 可以增強(qiáng)代碼的復(fù)用性 減少冗余代碼

用代碼來(lái)舉個(gè)例子

class person
{public:
	void Print()
	{cout<< "name : "<< _name<< endl;
		cout<< "age : "<< _age<< endl;
	}
protected:
	string _name = "zhangsan";
	int _age = 18;
};

// 學(xué)生類(lèi)
class student :public person
{public:
private:
	int _stuid;
};
// 教師類(lèi)
class teacher :public person
{public:
private:
	int _jobid;
};

從而達(dá)到一個(gè)這樣子的效果

在這里插入圖片描述
繼承之后父類(lèi)的所有成員 包括成員變量和方法 都會(huì)成為子類(lèi)的一部分

繼承的定義 定義格式

繼承的定義方式如下
在這里插入圖片描述

繼承方式和訪(fǎng)問(wèn)限定符

我們都知道 訪(fǎng)問(wèn)限定符有三種

  1. public訪(fǎng)問(wèn)
  2. protected訪(fǎng)問(wèn)
  3. private訪(fǎng)問(wèn)

繼承的方式也有三種

  1. public繼承
  2. protected繼承
  3. private繼承

基類(lèi)當(dāng)中被不同訪(fǎng)問(wèn)限定符修飾的成員,以不同的繼承方式繼承到派生類(lèi)當(dāng)中后,該成員最終在派生類(lèi)當(dāng)中的訪(fǎng)問(wèn)方式將會(huì)發(fā)生變化。

如下圖

在這里插入圖片描述
實(shí)際上稍作觀察之后我們就能發(fā)現(xiàn)

在子類(lèi)中的訪(fǎng)問(wèn)訪(fǎng)問(wèn)方式遵循以下規(guī)則

  1. 當(dāng)父類(lèi)的訪(fǎng)問(wèn)方式為protected或者public時(shí) 在子類(lèi)中它會(huì)變成繼承方式和父類(lèi)訪(fǎng)問(wèn)方式中權(quán)限更小的值

什么意思呢? 比如說(shuō)父類(lèi)的訪(fǎng)問(wèn)方式是public 子類(lèi)使用protected繼承 那么它在子類(lèi)中的訪(fǎng)問(wèn)方式就變成protected了

如果父類(lèi)的訪(fǎng)問(wèn)方式是protected 子類(lèi)使用public繼承 那么它在子類(lèi)中的訪(fǎng)問(wèn)方式還是protected

  1. 當(dāng)父類(lèi)的訪(fǎng)問(wèn)方式是privated時(shí) 不管子類(lèi)使用何種繼承方式 都是不可見(jiàn)的

那么不可見(jiàn)又是什么意思呢?

我們寫(xiě)出下面的一段代碼

class person
{public:
	void Print()
	{cout<< "name : "<< _name<< endl;
		cout<< "age : "<< _age<< endl;
	}
protected:
	string _name = "zhangsan";
	int _age = 18;
private:
	string _add = "chenghuadadao";
};

// 學(xué)生類(lèi)
class student :public person
{public:
	void testerr()
	{cout<< this->_add<< endl;
	}

我們可以發(fā)現(xiàn) 在學(xué)生類(lèi)中 我們是無(wú)法訪(fǎng)問(wèn)父類(lèi)中的_add的

在這里插入圖片描述
事實(shí)上這里的編譯器也直接給了我們紅線(xiàn)報(bào)錯(cuò)

這里其實(shí)也從側(cè)面說(shuō)明了protected訪(fǎng)問(wèn)限定符為什么會(huì)出現(xiàn)

它的作用就是為了不想讓類(lèi)外部訪(fǎng)問(wèn) 而想讓子類(lèi)訪(fǎng)問(wèn)

但是 我們?cè)趯?shí)際寫(xiě)代碼的過(guò)程中一般都是用public繼承

這也是C++被人詬病的語(yǔ)法缺點(diǎn)之一 后續(xù)的python語(yǔ)言甚

至都沒(méi)有繼承方式這一說(shuō)了

默認(rèn)繼承方式

這里我們不推薦使用默認(rèn)繼承方式 所以也就不多講了

我們只需要知道兩點(diǎn)

class的默認(rèn)繼承方式是 private

struct的默認(rèn)繼承方式是 public

基類(lèi)和派生類(lèi)的賦值轉(zhuǎn)換

派生類(lèi)對(duì)象可以賦值給基類(lèi)的對(duì)象 基類(lèi)的指針 基類(lèi)的引用

在這個(gè)過(guò)程當(dāng)中會(huì)發(fā)生基類(lèi)和派生類(lèi)對(duì)象之間的賦值轉(zhuǎn)換

我們來(lái)看代碼

class person
{public:
	string _name;
	string _sex;
	int age;
};

class student : public person
{private:
	int _stuid;
};

像上面的代碼 我們寫(xiě)下下面這些操作全部是合法的

student s;
	person p = s;
	person* ptr = &s;
	person& ref = s;

對(duì)于我們上面的操作 C++中給了一個(gè)比較專(zhuān)業(yè)的名詞叫做切片

意思就是將子類(lèi)中繼承基類(lèi)的那部分切出來(lái) 賦值給基類(lèi)

對(duì)象賦值
在這里插入圖片描述
指針賦值

在這里插入圖片描述
引用賦值

在這里插入圖片描述

那么這個(gè)時(shí)候我們?cè)傧胍幌?基類(lèi)對(duì)象能否賦值給子類(lèi)呢

在這里插入圖片描述
我們寫(xiě)出上面的代碼 結(jié)果發(fā)現(xiàn)報(bào)錯(cuò)了

其實(shí)想想也能明白 基類(lèi)相對(duì)于子類(lèi)來(lái)說(shuō)會(huì)少一些東西

所以肯定是不能切片賦值的

但是子類(lèi)的指針和引用可以通過(guò)強(qiáng)制類(lèi)型轉(zhuǎn)換的方式來(lái)賦值

代碼和顯示效果如下

student* ptrs = (student *)&p;
	student& refs = (student&)p;

在這里插入圖片描述
同樣的 我們知道有這個(gè)方式存在就好 不建議使用!

繼承中的作用域

接下來(lái)我們要學(xué)習(xí)的是C++繼承中的又一大缺陷(bushi) 特性之一

還是一樣 我們先來(lái)看代碼

//父類(lèi)
class Person
{protected:
	int _num = 111;
};
//子類(lèi)
class Student : public Person
{public:
	void fun()
	{cout<< _num<< endl;
	}
protected:
	int _num = 999;
};
int main()
{Student s;
	s.fun(); 
	return 0;
}

我們?nèi)绻蒙仙厦娴囊欢未a 并且調(diào)用fun函數(shù)的話(huà) 由于函數(shù)的局部性原理 我們會(huì)得到子類(lèi)中的num值 如下圖

在這里插入圖片描述

這個(gè)時(shí)候如果我們想要訪(fǎng)問(wèn)父類(lèi)中的num就需要使用域操作符

void fun()
	{cout<< Person::_num<< endl;
	}

在這里插入圖片描述

在繼承體系中的基類(lèi)和派生類(lèi)都有獨(dú)立的作用域。若子類(lèi)和父類(lèi)中有同名成員,子類(lèi)成員將屏蔽父類(lèi)對(duì)同名成員的直接訪(fǎng)問(wèn),這種情況叫隱藏,也叫重定義。

需要注意的是,如果是成員函數(shù)的隱藏,只需要函數(shù)名相同就構(gòu)成隱藏。

還是拿上面的代碼距離 我們給父類(lèi)中加上一個(gè)fun函數(shù)

class Person
{public:
	void fun()
	{cout<< _num<< endl;
	}

像這樣 如果我們要調(diào)用父類(lèi)里面的person函數(shù)只能加上一個(gè)域操作符 如下圖

在這里插入圖片描述

特別的 這兩個(gè)函數(shù)不構(gòu)成函數(shù)重載 因?yàn)闃?gòu)成函數(shù)重載的兩個(gè)函數(shù)一定要在同一作用域

我們?cè)谡嬲龑?xiě)代碼的時(shí)候應(yīng)該避免重名的問(wèn)題

派生類(lèi)的默認(rèn)成員函數(shù)

在這里插入圖片描述

我們都知道 類(lèi)有六大默認(rèn)成員函數(shù)

下面我們看看派生類(lèi)當(dāng)中的默認(rèn)成員函數(shù),與普通類(lèi)的默認(rèn)成員函數(shù)的不同之處。

其實(shí)這里只要記住一點(diǎn)就好

凡是與基類(lèi)相關(guān)的部分 都要調(diào)用基類(lèi)的相關(guān)函數(shù)

接下來(lái)我們來(lái)看代碼

這是基類(lèi)person的代碼

//基類(lèi)
class Person
{public:
	//構(gòu)造函數(shù)
	Person(const string& name = "peter")
		:_name(name)
	{cout<< "Person()"<< endl;
	}
	//拷貝構(gòu)造函數(shù)
	Person(const Person& p)
		:_name(p._name)
	{cout<< "Person(const Person& p)"<< endl;
	}
	//賦值運(yùn)算符重載函數(shù)
	Person& operator=(const Person& p)
	{cout<< "Person& operator=(const Person& p)"<< endl;
		if (this != &p)
		{	_name = p._name;
		}
		return *this;
	}
	//析構(gòu)函數(shù)
	~Person()
	{cout<< "~Person()"<< endl;
	}
private:
	string _name; //姓名
};

這是子類(lèi)student的代碼

//派生類(lèi)
class Student : public Person
{public:
	//構(gòu)造函數(shù)
	Student(const string& name, int id)
		:Person(name) //調(diào)用基類(lèi)的構(gòu)造函數(shù)初始化基類(lèi)的那一部分成員
		, _id(id) //初始化派生類(lèi)的成員
	{cout<< "Student()"<< endl;
	}
	//拷貝構(gòu)造函數(shù)
	Student(const Student& s)
		:Person(s) //調(diào)用基類(lèi)的拷貝構(gòu)造函數(shù)完成基類(lèi)成員的拷貝構(gòu)造
		, _id(s._id) //拷貝構(gòu)造派生類(lèi)的成員
	{cout<< "Student(const Student& s)"<< endl;
	}
	//賦值運(yùn)算符重載函數(shù)
	Student& operator=(const Student& s)
	{cout<< "Student& operator=(const Student& s)"<< endl;
		if (this != &s)
		{	Person::operator=(s); //調(diào)用基類(lèi)的operator=完成基類(lèi)成員的賦值
			_id = s._id; //完成派生類(lèi)成員的賦值
		}
		return *this;
	}
	//析構(gòu)函數(shù)
	~Student()
	{cout<< "~Student()"<< endl;
		//派生類(lèi)的析構(gòu)函數(shù)會(huì)在被調(diào)用完成后自動(dòng)調(diào)用基類(lèi)的析構(gòu)函數(shù)
	}
private:
	int _id; //學(xué)號(hào)
};

是不是發(fā)現(xiàn)完全符合我們上面的推論

這里有兩個(gè)特殊結(jié)論

派生類(lèi)對(duì)象初始化時(shí),會(huì)先調(diào)用基類(lèi)的構(gòu)造函數(shù)再調(diào)用派生類(lèi)的構(gòu)造函數(shù)。
派生類(lèi)對(duì)象在析構(gòu)時(shí),會(huì)先調(diào)用派生類(lèi)的析構(gòu)函數(shù)再調(diào)用基類(lèi)的析構(gòu)函數(shù)。

所以說(shuō)我們?cè)谂缮?lèi)的析構(gòu)函數(shù)中不需要在顯示調(diào)用基類(lèi)的析構(gòu)函數(shù)了

在這里插入圖片描述
我們可以發(fā)現(xiàn) 假設(shè)我們顯示的調(diào)用基類(lèi)的析構(gòu)函數(shù)的話(huà) 就會(huì)析構(gòu)兩次

這在一些情況(開(kāi)辟釋放內(nèi)存)下會(huì)發(fā)生錯(cuò)誤

此外還有以下三個(gè)注意點(diǎn)

  1. 派生類(lèi)和基類(lèi)的賦值運(yùn)算符重載函數(shù)因?yàn)楹瘮?shù)名相同構(gòu)成隱藏,因此在派生類(lèi)當(dāng)中調(diào)用基類(lèi)的賦值運(yùn)算符重載函數(shù)時(shí),需要使用作用域限定符進(jìn)行指定調(diào)用。
  2. 由于多態(tài)的某些原因,任何類(lèi)的析構(gòu)函數(shù)名都會(huì)被統(tǒng)一處理為destructor();。因此,派生類(lèi)和基類(lèi)的析構(gòu)函數(shù)也會(huì)因?yàn)楹瘮?shù)名相同構(gòu)成隱藏,若是我們需要在某處調(diào)用基類(lèi)的析構(gòu)函數(shù),那么就要使用作用域限定符進(jìn)行指定調(diào)用。
  3. 在派生類(lèi)的拷貝構(gòu)造函數(shù)和operator=當(dāng)中調(diào)用基類(lèi)的拷貝構(gòu)造函數(shù)和operator=的傳參方式是一個(gè)切片行為,都是將派生類(lèi)對(duì)象直接賦值給基類(lèi)的引用。
繼承與友元

這里還是記住一點(diǎn)就好 友元關(guān)系不可以繼承

比如說(shuō)

class Student;
class Person
{public:
 friend void Display(const Person& p, const Student& s);
protected:
 string _name; // 姓名
};
class Student : public Person
{protected:
 int _stuNum; // 學(xué)號(hào)
};
void Display(const Person& p, const Student& s)
{cout<< p._name<< endl;
 cout<< s._stuNum<< endl;
}
void main()
{Person p;
 Student s;
 Display(p, s);
}

我們這里Display函數(shù)不能訪(fǎng)問(wèn)student
在這里插入圖片描述

要想訪(fǎng)問(wèn)的話(huà)必須要在student中也聲明友元

class Student : public Person
{public:
	//聲明Display是Student的友元
	friend void Display(const Person& p, const Student& s);
protected:
	int _id; //學(xué)號(hào)
};

這個(gè)時(shí)候我們就可以使用dis函數(shù)訪(fǎng)問(wèn)它們的內(nèi)容了

在這里插入圖片描述

繼承與靜態(tài)成員

我們都知道 靜態(tài)變量是儲(chǔ)存在靜態(tài)區(qū)里面的 那么不管我們派生出多少個(gè)子類(lèi) 實(shí)際上它們的靜態(tài)變量?jī)?chǔ)存地址都是一樣的

我們可以使用下面的代碼來(lái)證明

class person
{public:
	static int _count ;
};

int person::_count = 0;
class student :public person
{public:
	void test()
	{_count++;
	}
};

我們?cè)囍{(diào)用子類(lèi)中的函數(shù)讓_count++

之后打印子類(lèi)和父類(lèi)中的_count看看是不是都是1

在這里插入圖片描述

繼承方式 單繼承

單繼承:一個(gè)子類(lèi)只有一個(gè)直接父類(lèi)時(shí)稱(chēng)這個(gè)繼承關(guān)系為單繼承。

比如下面這種方式

在這里插入圖片描述

多繼承

多繼承:一個(gè)子類(lèi)有兩個(gè)或兩個(gè)以上直接父類(lèi)時(shí)稱(chēng)這個(gè)繼承關(guān)系為多繼承。

比如說(shuō)下面這樣子

在這里插入圖片描述

菱形繼承

菱形繼承:菱形繼承是多繼承的一種特殊情況。

在這里插入圖片描述
從上面的圖我們不難看出 菱形繼承一定存在著數(shù)據(jù)冗余和二義性的問(wèn)題

比如說(shuō)我們來(lái)看下面的代碼

class Person
{public:
	string _name; //姓名
};
class Student : public Person
{protected:
	int _num; //學(xué)號(hào)
};
class Teacher : public Person
{protected:
	int _id; //職工編號(hào)
};
class Assistant : public Student, public Teacher
{protected:
	string _majorCourse; //主修課程
};
int main()
{Assistant a;
	a._name = "peter"; //二義性:無(wú)法明確知道要訪(fǎng)問(wèn)哪一個(gè)_name
	return 0;
}

我們運(yùn)行上面的代碼之后就會(huì)發(fā)生一個(gè)這樣子的問(wèn)題
在這里插入圖片描述
對(duì)于二義性問(wèn)題 我們可以通過(guò)指定作用域來(lái)解決

Assistant a;
	a.Student::_name = "peter"; 
	a.Teacher::_name = "peter2";

在這里插入圖片描述
但是數(shù)據(jù)冗余的問(wèn)題缺一定解決不了 如下圖

在這里插入圖片描述
這個(gè)時(shí)候就輪到我們的虛繼承出場(chǎng)了

菱形的虛擬繼承

在這里插入圖片描述
這種繼承方式就是為了專(zhuān)門(mén)解決菱形繼承的二義性還有數(shù)據(jù)冗余問(wèn)題被發(fā)明出來(lái)的

我們只需要在上面的繼承方式前加上這段代碼

class Person
{public:
	string _name; //姓名
};
class Student : virtual public Person //虛擬繼承
{protected:
	int _num; //學(xué)號(hào)
};
class Teacher : virtual public Person //虛擬繼承
{protected:
	int _id; //職工編號(hào)
};
class Assistant : public Student, public Teacher
{protected:
	string _majorCourse; //主修課程
};
int main()
{Assistant a;
	a._name = "peter"; //無(wú)二義性
	return 0;
}

在這里插入圖片描述
這個(gè)時(shí)候我們便發(fā)現(xiàn)不會(huì)報(bào)錯(cuò)了

此時(shí) 不管你是訪(fǎng)問(wèn)teacher還是student中的name 都是訪(fǎng)問(wèn)的一個(gè)地址

在這里插入圖片描述

菱形虛擬繼承的原理

我們首先看看 如果我們不適用菱形虛擬繼承 那么這幾個(gè)類(lèi)在內(nèi)存中會(huì)是怎么樣分布的

class A
{public:
	int _a;
};
class B : public A
{public:
	int _b;
};
class C : public A
{public:
	int _c;
};
class D : public B, public C
{public:
	int _d;
};
int main()
{D d;
	d.B::_a = 1;
	d.C::_a = 2;
	d._b = 3;
	d._c = 4;
	d._d = 5;
	return 0;
}

接下來(lái)我們打開(kāi)內(nèi)存窗口

在這里插入圖片描述
我們可以發(fā)現(xiàn) 它在內(nèi)存中的分布是這樣子的
(重點(diǎn)觀察_a 兩個(gè)a的地址不一樣)

在這里插入圖片描述
接下來(lái)我們看看虛繼承會(huì)是什么樣子的

#includeusing namespace std;
class A
{public:
	int _a;
};
class B : virtual public A
{public:
	int _b;
};
class C : virtual public A
{public:
	int _c;
};
class D : public B, public C
{public:
	int _d;
};
int main()
{D d;
	d.B::_a = 1;
	d.C::_a = 2;
	d._b = 3;
	d._c = 4;
	d._d = 5;
	return 0;
}

還是一樣 我們來(lái)打開(kāi)內(nèi)存窗口

在這里插入圖片描述

這個(gè)時(shí)候我們可以看到 _a被存放到了最后 而一開(kāi)始存放_(tái)a的兩個(gè)數(shù)據(jù)則被兩個(gè)奇怪的數(shù)據(jù)代替了

實(shí)際上呢 這兩個(gè)奇怪的數(shù)據(jù)就是指針

它們被叫做虛基表指針

分別指向一個(gè)虛基表 而我們通過(guò)虛基表則能夠找到_a的地址

如下圖

在這里插入圖片描述

繼承與組合

很多人都說(shuō)C++語(yǔ)法復(fù)雜,其實(shí)多繼承就是一個(gè)體現(xiàn)。有了多繼承,就可能存在菱形繼承,有了菱形繼承就有菱形虛擬繼承,底層實(shí)現(xiàn)就很復(fù)雜。所以一般不建議設(shè)計(jì)出菱形繼承,否則代碼在復(fù)雜度及性能上都容易出現(xiàn)問(wèn)題,當(dāng)菱形繼承出問(wèn)題時(shí)難以分析,并且會(huì)有一定的效率影響。

那么這個(gè)時(shí)候我們的組合就出現(xiàn)了

繼承和組合的區(qū)別有什么呢?

繼承是一種is-a的關(guān)系,也就是說(shuō)每個(gè)派生類(lèi)對(duì)象都是一個(gè)基類(lèi)對(duì)象;而組合是一種has-a的關(guān)系,若是B組合了A,那么每個(gè)B對(duì)象中都有一個(gè)A對(duì)象。

比如說(shuō)我們看下面的代碼

車(chē)和保時(shí)捷就是一種is a的關(guān)系 我們可以說(shuō) 保時(shí)捷是一輛車(chē)

所以說(shuō)這種情況使用繼承好一點(diǎn)

class  Car
{protected:
	string _colour; //顏色
	string _num; //車(chē)牌號(hào)
};
class Porsche : public Car
{;
};

但是呢 像車(chē)輪胎和保時(shí)捷 就是一種has a的關(guān)系了

我們只能說(shuō)保時(shí)捷有車(chē)輪胎 不能說(shuō)保時(shí)捷是車(chē)輪胎

class Tire
{protected:
	string _brand; //品牌
	size_t _size; //尺寸
};
class Car
{protected:
	string _colour; //顏色
	string _num; //車(chē)牌號(hào)
	Tire _t; // 這里就使用了一個(gè)包含關(guān)系
};

若是兩個(gè)類(lèi)之間既可以看作is-a的關(guān)系,又可以看作has-a的關(guān)系,則優(yōu)先使用組合。

  1. 繼承允許你根據(jù)基類(lèi)的實(shí)現(xiàn)來(lái)定義派生類(lèi)的實(shí)現(xiàn),這種通過(guò)生成派生類(lèi)的復(fù)用通常被稱(chēng)為白箱復(fù)用(White-box
    reuse)。術(shù)語(yǔ)“白箱”是相對(duì)可視性而言:在繼承方式中,基類(lèi)的內(nèi)部細(xì)節(jié)對(duì)于派生類(lèi)可見(jiàn),繼承一定程度破壞了基類(lèi)的封裝,基類(lèi)的改變對(duì)派生類(lèi)有很大的影響,派生類(lèi)和基類(lèi)間的依賴(lài)性關(guān)系很強(qiáng),耦合度高。
  2. 組合是類(lèi)繼承之外的另一種復(fù)用選擇,新的更復(fù)雜的功能可以通過(guò)組裝或組合對(duì)象來(lái)獲得。對(duì)象組合要求被組合的對(duì)象具有良好定義的接口,這種復(fù)用風(fēng)格被稱(chēng)之為黑箱復(fù)用(Black-box reuse),因?yàn)閷?duì)象的內(nèi)部細(xì)節(jié)是不可見(jiàn)的,對(duì)象只以“黑箱”的形式出現(xiàn),組合類(lèi)之間沒(méi)有很強(qiáng)的依賴(lài)關(guān)系,耦合度低,優(yōu)先使用對(duì)象組合有助于你保持每個(gè)類(lèi)被封裝。
  3. 實(shí)際中盡量多使用組合,組合的耦合度低,代碼維護(hù)性好。不過(guò)繼承也是有用武之地的,有些關(guān)系就適合用繼承,另外要實(shí)現(xiàn)多態(tài)也必須要繼承。若是類(lèi)之間的關(guān)系既可以用繼承,又可以用組合,則優(yōu)先使用組合。
筆試面試題
  1. 什么是菱形繼承?菱形繼承的問(wèn)題是什么?

菱形繼承是多繼承的一種特殊情況,兩個(gè)子類(lèi)繼承同一個(gè)父類(lèi),而又有子類(lèi)同時(shí)繼承這兩個(gè)子類(lèi),我們稱(chēng)這種繼承為菱形繼承。
菱形繼承因?yàn)樽宇?lèi)對(duì)象當(dāng)中會(huì)有兩份父類(lèi)的成員,因此會(huì)導(dǎo)致數(shù)據(jù)冗余和二義性的問(wèn)題。

  1. 什么是菱形虛擬繼承?如何解決數(shù)據(jù)冗余和二義性?
    在這里插入圖片描述

菱形虛擬繼承是指在菱形繼承的腰部使用虛擬繼承(virtual)的繼承方式,菱形虛擬繼承對(duì)于D類(lèi)對(duì)象當(dāng)中重復(fù)的A類(lèi)成員只存儲(chǔ)一份,然后采用虛基表指針和虛基表使得D類(lèi)對(duì)象當(dāng)中繼承的B類(lèi)和C類(lèi)可以找到自己繼承的A類(lèi)成員,從而解決了數(shù)據(jù)冗余和二義性的問(wèn)題。

  1. 繼承和組合的區(qū)別?什么時(shí)候用繼承?什么時(shí)候用組合?

1 繼承是一種is-a的關(guān)系,而組合是一種has-a的關(guān)系。如果兩個(gè)類(lèi)之間是is-a的關(guān)系,使用繼承;
2 如果兩個(gè)類(lèi)之間是has-a的關(guān)系,則使用組合;
3 如果兩個(gè)類(lèi)之間的關(guān)系既可以看作is-a的關(guān)系,又可以看作has-a的關(guān)系,則優(yōu)先使用組合。

總結(jié)

在這里插入圖片描述
本篇博客主要介紹了C++繼承的一些相關(guān)知識(shí)

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

文章名稱(chēng):C++進(jìn)階繼承-創(chuàng)新互聯(lián)
瀏覽路徑:http://jinyejixie.com/article14/csphge.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化、網(wǎng)站營(yíng)銷(xiāo)用戶(hù)體驗(yàn)、自適應(yīng)網(wǎng)站、外貿(mào)建站、移動(dòng)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名
团风县| 海伦市| 龙游县| 出国| 涿鹿县| 鄂尔多斯市| 云阳县| 子洲县| 北海市| 樟树市| 太原市| 梓潼县| 乳山市| 磴口县| 北川| 呼玛县| 大理市| 南和县| 崇仁县| 永仁县| 中西区| 霍山县| 改则县| 丰台区| 安国市| 呼伦贝尔市| 大方县| 都匀市| 马龙县| 汶川县| 邮箱| 于田县| 合水县| 黄大仙区| 德惠市| 新沂市| 肇源县| 伊宁市| 阳西县| 清徐县| 德保县|