国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解

這篇具有很好參考價值的文章主要介紹了【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

??專欄介紹:淺嘗C++專欄是用于記錄C++語法基礎、STL及內存剖析等。
??每日格言:每日努力一點點,技術變化看得見。


繼承的概念及定義

繼承的概念

我們生活中也有繼承的例子,例如:小明繼承了孫老師傅做拉面的手藝。繼承就是一種延續(xù)、復用的方式。C++為了提高代碼的可復用性,引入了繼承機制,概念如下↓↓↓

繼承機制是面向對象程序設計使代碼可以復用的最重要的手段,它允許程序員在保持原有類特性的基礎上進行擴展,增加功能,這樣產(chǎn)生新的類,稱派生類。繼承呈現(xiàn)了面向對象程序設計的層次結構,體現(xiàn)了由簡單到復雜的認知過程。以前我們接觸的復用都是函數(shù)復用,繼承是類設計層次的復用。

繼承的定義

定義格式

下圖演示的繼承的格式,其中Person是父類,也稱作基類;Student是子類,也稱作派生類
【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

下面給出代碼示例(下面代碼中,Student類繼承父類Person)↓↓↓

#include <iostream>
using namespace std;

class Person
{
public:
	void Show()
	{
		cout <<  _name << " " << _age << endl;
	}
protected:
	string _name = "jammingpro";	//姓名
	int _age = 18;					//年齡
};

class Student : public Person
{
private:
	int _stuId;
};

int main()
{
	Person p;
	Student s;
	p.Show();
	s.Show();
	return 0;
}

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言
上面代碼中,Student繼承父類Person的成員(成員函數(shù)+成員變量)后,這些成員都變成了子類的一部分。這里的Student復用了Person的成員。通過監(jiān)視窗口可以看到,Student中也有自己的_name、_age成員變量。
【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

繼承關系與訪問限定符

在C++的繼承機制中,包含3種繼承方式及3種類訪問限定符(如下圖所示),下面將分別介紹它們。
【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

我們在學習類和對象時,就已經(jīng)接觸過訪問限定符。其中public成員可以在類外訪問,而protected與private成員不能在類外訪問。但這里的protected和private在繼承時是有區(qū)別的:
●如果父類愿意讓自己的成員被外界訪問并愿意讓子類繼承,則定義為public的;
●如果父類希望自己的成員不被外界訪問而愿意讓子類繼承,則需要定義為protected;
●如果父類不希望自己的成員被外界訪問、被繼承,則需要定義為private的。

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

父類中的訪問限定符表示父類愿不愿意讓子類繼承,而繼承方式則可以讓子類縮小父類成員的訪問權限,但不能放大父類成員的訪問權限。

父類成員/子類繼承方式 public繼承 protected繼承 private繼承
父類的public成員 變?yōu)樽宇惖膒ublic成員 變?yōu)樽宇恜rotected成員 變?yōu)樽宇惖膒rivate成員
父類的protected成員 變?yōu)樽宇惖膒rotected成員 變?yōu)樽宇惖膒rotected成員 變?yōu)樽宇惖膒rivate成員
父類的private成員 子類不可見 子類不可見 子類不可見

總結

  1. 基類private成員在派生類中無論以什么方式繼承都是不可見的。這里的不可見是指基類的私有成員還是被繼承到了派生類對象中,但是語法上限制派生類對象不管在類里面還是類外面
    都不能去訪問它。

  2. 基類private成員在派生類中是不能被訪問,如果基類成員不想在類外直接被訪問,但需要在派生類中能訪問,就定義為protected。可以看出保護成員限定符是因繼承才出現(xiàn)的。

  3. 實際上面的表格我們進行一下總結會發(fā)現(xiàn),基類的私有成員在子類都是不可見?;惖钠渌蓡T在子類的訪問方式等于Min{成員在基類的訪問限定符,繼承方式},其中,public>protected>private。

  4. 使用關鍵字class時默認的繼承方式是private,使用struct時默認的繼承方式是public,不過最好顯示的寫出繼承方式。

  5. 在實際運用中一般使用都是public繼承,幾乎很少使用protetced/private繼承,也不提倡使用protetced/private繼承,因為protetced/private繼承下來的成員都只能在派生類的類里面使用,實際中擴展維護性不強。

針對于總結中的第一點,父類private成員實際上還是被子類繼承了,只是子類無法訪問,下面使用代碼驗證↓↓↓

#include <iostream>
using namespace std;

class Base
{
private:
	int _base;
};

class Son : public Base
{}

int main()
{
	Son s;
	return 0;
}

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

基類和派生類對象賦值轉換

●派生類對象可以賦值給基類的對象/基類的指針/基類的引用。這里有個形象的說法叫切片或者切割。寓意把派生類中父類那部分切來賦值過去。

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言
下面給出代碼示例↓↓↓

#include <iostream>
using namespace std;

class Person
{
public:
	Person()
	{}
	Person(const string& name, const char& sex, const int& age)
		:_name(name)
		,_sex(sex)
		,_age(age)
	{}
protected:
	string _name;
	char _sex;
	int _age;
};

class Student : public Person
{
public:
	Student(const string& name, const char& sex, const int& age, const int& stuId)
		:Person(name, sex, age)
		,_stuId(stuId)
	{}
private:
	int _stuId;
};

int main()
{
	Student s("Jammingpro", 'M', 18, 123456);
	Person p;
	p=s;
	return 0;
}

從監(jiān)視窗口可以看到,Person對象保存了Student對象的父類成員部分,而舍棄了子類自有成員,這就是切片。
【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

●基類對象不能賦值給派生類對象。(基類對象無法用于構造派生類對象,也無法使用派生類對象的拷貝賦值函數(shù);但可以顯示提供派生類賦值給基類的operator=實現(xiàn))

★ps:由于派生類中的成員函數(shù)、成員對象一般情況下都會多于基類,如果基類直接賦值給派生類會導致部分成員數(shù)值不確定。因此,C++默認不提供基類賦值給派生類。

●基類的指針或者引用可以通過強制類型轉換賦值給派生類的指針或者引用。但是必須是基類的指針指向派生類對象時才是安全的。

下面代碼演示了基類賦值給派生類指針,派生類賦值給基類指針↓↓↓

#include <iostream>
using namespace std;

class Person
{
public:
	Person()
	{}
	Person(const string& name, const char& sex, const int& age)
		:_name(name)
		, _sex(sex)
		, _age(age)
	{}
	string _name;
	char _sex;
	int _age;
};

class Student : public Person
{
public:
	Student(const string& name, const char& sex, const int& age, const int& stuId)
		:Person(name, sex, age)
		, _stuId(stuId)
	{}
	int _stuId;
};

int main()
{
	Student s("Jammingpro", 'M', 18, 123456);
	Person p("xiaoming", 'M', 20);
	
	Person* p_s = &s;//安全
	Student* s_p = (Student*) & p;//不安全

	cout << s_p->_stuId << endl;

	return 0;
}

為什么說,Student* s_p = (Student*) & p;是不安全的呢?由于Person對象中沒有申請_stuId的空間,但在Student*類型看來,它認為它指向的對象有_stuId成員。如果用戶訪問了s_p->_stuId可能會因為內存非法訪問而報錯。
【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

繼承中的作用域

  1. 在繼承體系中基類和派生類都有獨立的作用域。
  2. 子類和父類中有同名成員,子類成員將屏蔽父類對同名成員的直接訪問,這種情況叫隱藏,也叫重定義。(在子類成員函數(shù)中,可以使用 基類::基類成員 顯示訪問)
  3. 需要注意的是如果是成員函數(shù)的隱藏,只需要函數(shù)名相同就構成隱藏(而不需要返回值相同,或是參數(shù)列表相同)。
  4. 注意在實際中在繼承體系里面最好不要定義同名的成員。

下面給出派生類成員變量與基類成員變量同名的例子↓↓↓
下面代碼中,由于Son類中的成員變量與Base類中的成員變量重名,構成了隱藏。如果使用Son s; cout << s._name << endl;,則只能訪問到Son對象中的成員變量,而無法訪問到父類中的_name成員變量。若需要訪問父類的_name成員變量,則可以使用類型+類作用域符號::來訪問,即s.Base::_name。

#include <iostream>
using namespace std;

class Base
{
public:
	string _name = "Jammingpro";
};

class Son : public Base
{
public:
	string _name = "xiaoming";
};

int main()
{
	Son s;
	cout << s._name << endl;
	cout << s.Base::_name << endl;
	return 0;
}

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言
下面給出派生類成員函數(shù)與基類成員函數(shù)同名的例子↓↓↓這里與成員變量同名的情況相同,同名成員函數(shù)也會構成隱藏關系,如果需要訪問父類的同名成員函數(shù),需要使用類名+類作用域運算符::。

#include <iostream>
using namespace std;

class Base
{
public:
	void Show()
	{
		cout << "I am _Base" << endl;
	}
};

class Son : public Base
{
public:
	void Show()
	{
		cout << "I am _Son" << endl;
	}
};

int main()
{
	Son s;
	s.Show();
	s.Base::Show();
	return 0;
}

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言
★( ??? )?test:下面的兩個同名函數(shù)(函數(shù)名相同,參數(shù)列表不同)分別屬于基類和派生類,它們構成的關系是隱藏還是函數(shù)重載呢?

#include <iostream>
using namespace std;

class Base
{
public:
	void print(char ch)
	{
		cout << "Base->" << ch << endl;
	}
};

class Son : public Base
{
public:
	void print(int num)
	{
		cout << "Son->" << num << endl;
	}
};

int main()
{
	Son s;
	s.print('A');
	return 0;
}

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言
Base中的成員函數(shù)比Son中的成員函數(shù)更匹配(不需要隱式類型轉換),而這里還是調用Son中的成員函數(shù),說明兩者構成的關系是隱藏,而不是函數(shù)重載。這里要注意:在繼承關系中,派生類與基類只要存在同名函數(shù)(不管參數(shù)列表、返回值是否相同),都是隱藏關系。

派生類的默認成員函數(shù)

6個默認成員函數(shù),“默認”的意思就是指我們不寫,編譯器會變我們自動生成一個,那么在派生類中,這幾個成員函數(shù)是如何生成的呢?

  1. 派生類的構造函數(shù)必須調用基類的構造函數(shù)初始化基類的那一部分成員。如果基類沒有默認的構造函數(shù),則必須在派生類構造函數(shù)的初始化列表階段顯示調用。

基類提供默認構造函數(shù)的情況
派生類在構造時,會自動調用基類的構造函數(shù)↓↓↓

#include <iostream>
using namespace std;

class Base
{
public:
	Base()
	{
		cout << "Base() is called" << endl;
	}
};

class Son : public Base
{
public:
	Son()
	{
		cout << "Son() is called" << endl;
	}
};

int main()
{
	Son s;
	return 0;
}

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言
基類沒有提供默認構造函數(shù)的情況
基類沒有提供默認構造時,子類必須在初始化參數(shù)列表中顯示調用基類的構造函數(shù),否則會報錯。

#include <iostream>
using namespace std;

class Base
{
public:
	Base(int b)
		:_b(b)
	{
		cout << "Base(int b) is called" << endl;
	}
private:
	int _b
};

class Son : public Base
{
public:
	Son(int b)
		:Base(b)
	{
		cout << "Son() is called" << endl;
	}
};

int main()
{
	Son s(5);
	return 0;
}

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

  1. 派生類的拷貝構造函數(shù)必須調用基類的拷貝構造完成基類的拷貝初始化。
#include <iostream>
using namespace std;

class Base
{
public:
	Base(int b)
		:_b(b)
	{}
	Base(const Base& b)
	{
		_b = b._b;
		cout << "Base(const Base& b) is called" << endl;
	}
private:
	int _b;
};

class Son : public Base
{
public:
	Son(int s, int b)
		:_s(s)
		,Base(b)
	{}
	Son(const Son& s)
		:Base(s)
	{
		_s = s._s;
		cout << "Son(const Son& s) is called" << endl;
	}
private:
	int _s;
};

int main()
{
	Son s(55, 66);
	Son s2(s);
	return 0;
}

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言
如果我們將上面代碼中顯示調用基類構造函數(shù)的代碼去掉,則會出現(xiàn)如下報錯↓↓↓
【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言
★ps:對于上面的報錯,雖然可以通過給基類提供默認構造函數(shù)解決,但卻無法完成子類中的基類成員的拷貝操作。

  1. 派生類的operator=可以調用基類的operator=完成基類的復制,這樣可以避免代碼冗余(這里派生類調用基類的operator=不是必須的,只是因為基類已經(jīng)實現(xiàn)了該操作,派生類不必再重復編寫相同內容)。

下面代碼演示了派生類調用基類operator=函數(shù)帶來的代碼簡化↓↓↓

#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <string>
#include <cstring>
using namespace std;

class Person
{
public:
	Person(const string& name, const int& age, const char& gender)
		:_name(name)
		,_age(age)
		,_gender(gender)
	{}
	Person& operator=(const Person& p)
	{
		_name = p._name;
		_age = p._age;
		_gender = p._gender;
		return *this;
	}
	void Show()
	{
		cout << "My name is " << _name << ", I am " << _age << " years old, I am a " 
		<< (_gender == 'M' ? " boy " : "girl") << endl;
	}
private:
	string _name;
	int _age;
	char _gender;
};

class Student : public Person
{
public:
	Student(const string& name, const int& age, const char& gender, const char* detail)
		:Person(name, age, gender)
	{
		_detail = new char[strlen(detail) + 1];
		strcpy(_detail, detail);
	}
	Student& operator=(const Student& s)
	{
		Person::operator=(s);
		char* detail = new char[strlen(s._detail)];
		return *this;
	}
	void Show()
	{
		Person::Show();
		cout << "My detail infomation is " << _detail << endl;
	}
	~Student()
	{
		delete[] _detail;
	}
private:
	char* _detail;
};

int main()
{
	Student s("Jammingpro", 18, 'M', "He is good at coding");
	Student copy = s;
	s.Show();
}

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

  1. 派生類的析構函數(shù)會在被調用完成后自動調用基類的析構函數(shù)清理基類成員。因為這樣才能保證派生類對象先清理派生類成員再清理基類成員的順序。

  2. 派生類對象初始化先調用基類構造再調派生類構造。

下面代碼演示了基類與派生類的構造與析構順序↓↓↓

#include <iostream>
using namespace std;

class Base
{
public:
	Base()
	{
		cout << "Base() is called" << endl;
	}
	~Base()
	{
		cout << "~Base() is deleted obj" << endl;
	}
};

class Son : public Base
{
public:
	Son()
	{
		cout << "Son is called" << endl;
	}
	~Son()
	{
		cout << "~Son() is deleted obj" << endl;
	}
};

int main()
{
	Son s;
	return 0;
}

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

  1. 編譯器會對析構函數(shù)名進行特殊處理,處理成destrutor(),所以父類析構函數(shù)不加virtual的情況下,子類析構函數(shù)和父類析構函數(shù)構成隱藏關系。

★ps:關于virtual關鍵字將于多態(tài)中講解

繼承與友元

友元關系不能不繼承,也就是說:基類的友元不能訪問派生類的私有和保護成員。

下面代碼演示了友元關系無法繼承↓↓↓

#include <iostream>
using namespace std;

class Base
{
	friend void print();
private:
	int _base = 88;
};

class Son : Base
{
private:
	int _son = 66;
};

void print()
{
	Base b;
	cout << b._base << endl;
	Son s;
	cout << s._son << endl;
}

int main()
{
	print();
	return 0;
}

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

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

基類定義了static靜態(tài)成員,則整個繼承體系中只能有一個這樣的成員。無論派生出多少多少個子類,都只有一個static成員實例。

#include <iostream>
using namespace std;

class Base
{
public:
	static int val;
};

//靜態(tài)非const成員變量需要在類外初始化
int Base::val = 66;

class Son : public Base
{
};

class GrandSon : Son
{
};

int main()
{
	cout << &Base::val << endl;
	cout << &Son::val << endl;
	cout << &GrandSon::val << endl;
	return 0;
}

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

復雜的菱形繼承及菱形虛擬繼承

單繼承:一個子類只有一個直接父類時稱這個繼承關系為單繼承
【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言
下面是一份單繼承的代碼↓↓↓

#include <iostream>
using namespace std;

class Base
{
public:
	void base_func()
	{}
	int _base;
};

class Son : public Base
{
public:
	void son_func()
	{}
	int _son;
};

class GrandSon : public Son
{
public:
	void gs_func()
	{}
	int _gs;
};

int main()
{
	GrandSon gs;
	cout << &gs << endl;
	gs._base = 1;
	cout << &gs._base << endl;
	gs._son = 2;
	cout << &gs._son << endl;
	gs._gs = 3;
	cout << &gs._gs << endl;

	cout << "===================================" << endl;

	Son s;
	cout << &s << endl;
	s._base = 1;
	cout << &s._base << endl;
	s._son = 2;
	cout << &s._son << endl;

	return 0;
}

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

上述代碼調試時,通過監(jiān)視窗口查看結果如下圖所示。我們可以發(fā)現(xiàn),GrandSon對象保存了其祖先類Son、Base的成員變量。Son對象保存了其基類成員變量。
【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言
下圖為GrandSon對象的存儲情況↓↓↓
【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言
通過分析上面的執(zhí)行結果,可以得出如下結論:再單繼承中,某個類的成員變量放置于類空間最后,該成員變量前放置的是直接父類,再往上是爺爺類,以此類推。類對象的地址,與最頂層的祖先的成員變量地址相同。

多繼承:一個子類有兩個或以上直接父類時稱這個繼承關系為多繼承
【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言
下面給出多繼承的演示代碼↓↓↓

#include <iostream>
using namespace std;

class Base1
{
public:
	void base1_func()
	{}
	int _base1;
};

class Base2
{
public:
	void base2_func()
	{}
	int _base2;
};

class Son : public Base1, public Base2
{
public:
	void son_func()
	{}
	int _son;
};

int main()
{
	Son s;
	cout << &s << endl;
	s._base1 = 1;
	cout << &s._base1 << endl;
	s._base2 = 2;
	cout << &s._base2 << endl;
	s._son = 3;
	cout << &s._son << endl;
	return 0;
}

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言
如果Son先繼承Base1再繼承Base2,則會將Base1的成員變量放在前面,后繼承的Base2的成員變量放在后面。
【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言
如果將Son先繼承Base2,再繼承Base1呢?
【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

由上面的執(zhí)行結果可知,先繼承的基類的成員變量放置于類對象的前面位置,后即成的基類的成員變量放置于類對象的后面位置,類自身的成員變量放置于最后。

菱形繼承:菱形繼承是多繼承的一種特殊情況
【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言
下面給出多繼承的演示代碼↓↓↓

#include <iostream>
using namespace std;

class Share
{
public:
	void share_func()
	{}
	int _share;
};

class Base1 : Share
{
public:
	void base1_func()
	{}
	int _base1;
};

class Base2 : Share
{
public:
	void base2_func()
	{}
	int _base2;
};

class Son : public Base1, public Base2
{
public:
	void son_func()
	{}
	int _son;
};

int main()
{
	Son s;
	s._base1 = 1;
	s._base2 = 2;
	s._son = 3;
	return 0;
}

在上述代碼的監(jiān)視窗口可以看出菱形繼承有數(shù)據(jù)冗余和二義性的問題。s中繼承了兩份Share類的成員變量_share。
【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言
C++中為了避免菱形繼承導致的數(shù)據(jù)冗余和二義性,它引入了虛擬繼承。虛擬繼承可以解決菱形繼承的二義性和數(shù)據(jù)冗余的問題。下面給出修改后的代碼(引入虛擬繼承的代碼)↓↓↓

#include <iostream>
using namespace std;

class Share
{
public:
	void share_func()
	{}
	int _share;
};

class Base1 : virtual public Share
{
public:
	void base1_func()
	{}
	int _base1;
};

class Base2 : virtual public Share
{
public:
	void base2_func()
	{}
	int _base2;
};

class Son : public Base1, public Base2
{
public:
	void son_func()
	{}
	int _son;
};

int main()
{
	Son s;
	cout << &s << endl;
	s._share = 0;
	cout << &s._share << endl;
	s._base1 = 1;
	cout << &s._base1 << endl;
	s._base2 = 2;
	cout << &s._base2 << endl;
	s._son = 3;
	cout << &s._son << endl;
	return 0;
}

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解,淺嘗C++,c++,開發(fā)語言,c語言

這里是通過了兩個指針,指向的一張表。這兩個指針叫虛基表指針,這兩個表叫虛基表。虛基表中存的偏移量。通過偏移量可以找到下面的Share。

??歡迎進入淺嘗C++專欄,查看更多文章。
如果上述內容有任何問題,歡迎在下方留言區(qū)指正b( ̄▽ ̄)d文章來源地址http://www.zghlxwxcb.cn/news/detail-846131.html

到了這里,關于【淺嘗C++】繼承機制=>虛基表/菱形虛繼承/繼承的概念、定義/基類與派生類對象賦值轉換/派生類的默認成員函數(shù)等詳解的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 【C++】從0到1講繼承|復雜的菱形繼承

    【C++】從0到1講繼承|復雜的菱形繼承

    ? ? 個人主頁:??在肯德基吃麻辣燙 我的gitee:gitee倉庫 分享一句喜歡的話:熱烈的火焰,冰封在最沉默的火山深處。 本文主要講述的是繼承的概念,以及基類和派生類和衍生出的各種東西,還有多繼承,菱形繼承等,從0到1講解繼承。 與日常生活中的人的繼承相關,你可

    2024年02月16日
    瀏覽(18)
  • 【C++練級之路】【Lv.12】繼承(你真的了解菱形虛擬繼承嗎?)

    【C++練級之路】【Lv.12】繼承(你真的了解菱形虛擬繼承嗎?)

    快樂的流暢:個人主頁 個人專欄:《C語言》《數(shù)據(jù)結構世界》《進擊的C++》 遠方有一堆篝火,在為久候之人燃燒! 繼承(inheritance),是面向對象的三大特性之一。 它是面向對象編程中, 使代碼可以復用 的最重要的手段,它允許程序員在 保持原有類特性的基礎上進行擴展

    2024年03月14日
    瀏覽(30)
  • C++中菱形繼承中的多態(tài)在底層是如何實現(xiàn)的。

    C++中菱形繼承中的多態(tài)在底層是如何實現(xiàn)的。

    如果還不了解菱形繼承和多態(tài)的底層可以看這兩篇文章: C++中多態(tài)的底層實現(xiàn)_Qianxueban的博客-CSDN博客 C++的繼承以及virtual的底層實現(xiàn)_Qianxueban的博客-CSDN博客

    2024年02月09日
    瀏覽(18)
  • 【繼承】復雜的菱形繼承

    【繼承】復雜的菱形繼承

    博主首頁: ?有趣的中國人 ? 專欄首頁: ?C++進階 ? 本篇文章主要講解 菱形繼承 ? 的相關內容 目錄 1. 繼承與友元 2. 繼承與靜態(tài)成員 3.?復雜的菱形繼承及菱形虛擬繼承 3.1 繼承分類 3.2 菱形繼承導致的問題 3.3 虛擬繼承解決數(shù)據(jù)冗余的原理 4. 繼承和組合的區(qū)別 友元關系不

    2024年04月22日
    瀏覽(26)
  • C++--菱形繼承

    C++--菱形繼承

    1.什么是菱形繼承 ????????單繼承:一個子類只有一個直接父類時稱這個繼承關系為單繼承 ???????????????????????????????? ? ??????? 多繼承:一個子類有兩個或以上直接父類時稱這個繼承關系為多繼承 菱形繼承的問題:菱形繼承有數(shù)據(jù)冗余和二義性

    2024年02月15日
    瀏覽(15)
  • 【C++技能樹】繼承概念與解析

    【C++技能樹】繼承概念與解析

    Halo,這里是Ppeua。平時主要更新C++,數(shù)據(jù)結構算法,Linux與ROS…感興趣就關注我bua! ? 設想一個場景,你需要設計學生、老師、教授…的類,除了每個身份中獨有的信息,例如:學號,工號,教授身份號,但是他們都有一個共同的屬性,就是人.所以我們可以先設計一個類:人. 每設計一個

    2024年02月10日
    瀏覽(18)
  • C++虛基類

    C++虛基類

    如果一個派生類是從多個基類派生出來的,而這些基類又有一個共同的基類,則在這個派生類中訪問這個共同的基類中的成員時,可能會產(chǎn)生二義性。 比如有以下結構 以下程序會報錯,因為a具有二義性。 能夠看到a被初始化了兩次,我們希望a只被再第一次初始化以后就不再

    2024年02月08日
    瀏覽(14)
  • 想要入坑C++?當我拿出菱形虛擬繼承,閣下又該如何應對

    想要入坑C++?當我拿出菱形虛擬繼承,閣下又該如何應對

    ??作者簡介: 花想云 ,目前大二在讀 ,C/C++領域新星創(chuàng)作者、運維領域新星創(chuàng)作者、CSDN2023新星計劃導師、CSDN內容合伙人、阿里云專家博主、華為云云享專家致力于 C/C++、Linux 學習 ?? 本文收錄于 C++系列 ,本專欄主要內容為 C++ 初階、C++ 進階、STL 詳解等,專為大學生打造

    2024年02月07日
    瀏覽(22)
  • 【C++】繼承的基本特性(定義,賦值轉換,友元,靜態(tài)成員,虛擬繼承,默認成員函數(shù),作用域)

    【C++】繼承的基本特性(定義,賦值轉換,友元,靜態(tài)成員,虛擬繼承,默認成員函數(shù),作用域)

    ??博客主頁: 主頁 ??系列專欄: C++ ??感謝大家點贊??收藏?評論?? ??期待與大家一起進步! 它允許程序員在保持原有類特性的基礎上進行擴展,增加功能,這樣產(chǎn)生新的類,稱派生類。 Person是父類,也稱作基類。Student是子類,也稱作派生類 總結: 基類private成員

    2024年02月14日
    瀏覽(22)
  • 論文淺嘗 | 記憶力強還是健忘?深入探究語言模型的知識記憶機制

    論文淺嘗 | 記憶力強還是健忘?深入探究語言模型的知識記憶機制

    筆記整理:方潤楠,浙江大學碩士,研究方向為自然語言處理 鏈接:https://arxiv.org/abs/2305.09144 摘要 近年來,大規(guī)模預訓練語言模型展示出驚人的記憶能力,相比之下,未經(jīng)預訓練的普通神經(jīng)網(wǎng)絡存在著災難性遺忘的問題。為了研究這種記憶與遺忘出現(xiàn)的原因,并探求語言模

    2024年01月18日
    瀏覽(31)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包