《C++繼承詳解:從入門到理解公有、私有與保護繼承》

《C++繼承詳解:從入門到理解公有、私有與保護繼承》


文章目錄

  • 《C++繼承詳解:從入門到理解公有、私有與保護繼承》
  • 一、繼承的概念及定義
    • 1.1 繼承的概念
    • 1.2 繼承定義
      • 1.2.1 定義格式
      • 1.2.2 繼承基類成員訪問方式的變化
    • 1.3 繼承類模版
  • 二、基類和派生類間的轉換
  • 三、繼承中的作用域
    • 3.1 隱藏規則
    • 3.2 考察繼承作用域相關選擇題
  • 四、派生類的默認成員函數
    • 4.1 4個常見的默認成員函數
    • 4.2 實現一個不能被繼承的類
  • 五、繼承與友元
  • 六、繼承與靜態成員
  • 七、多繼承及其菱形繼承問題
    • 7.1 繼承模型
    • 7.2 虛繼承
    • 7.3 IO庫中的菱形虛擬繼承
  • 八、繼承和組合
  • 九、整體源代碼


一、繼承的概念及定義

1.1 繼承的概念

在這里插入圖片描述


在這里插入圖片描述
在這里插入圖片描述


在這里插入圖片描述在這里插入圖片描述


1.2 繼承定義

1.2.1 定義格式

在這里插入圖片描述在這里插入圖片描述


1.2.2 繼承基類成員訪問方式的變化

在這里插入圖片描述


在這里插入圖片描述


1.3 繼承類模版

繼承類模版就是繼承一個模版類,大框架和普通的繼承想吐,但是調用父類中的屬性或者行為時要指定在父類的哪個屬性或者行為,這樣是因為類模版的按需實例化,不指定就不會實例化,會報錯
下面是用繼承寫一個棧,這個棧繼承了父類vector
每次復用vector里面的成員函數時都要指定父類類域,否則報錯,找不到標識符


在這里插入圖片描述
在這里插入圖片描述

二、基類和派生類間的轉換

在這里插入圖片描述在這里插入圖片描述
在這里插入圖片描述


三、繼承中的作用域

3.1 隱藏規則

在這里插入圖片描述在這里插入圖片描述


3.2 考察繼承作用域相關選擇題

在這里插入圖片描述

四、派生類的默認成員函數

4.1 4個常見的默認成員函數

在這里插入圖片描述在這里插入圖片描述


在這里插入圖片描述


4.2 實現一個不能被繼承的類

在這里插入圖片描述

在這里插入圖片描述


五、繼承與友元

友元關系不能繼承,也就是說基類友元不能訪問派生類私有和保護成員
在這里插入圖片描述


六、繼承與靜態成員

基類定義了static靜態成員,則整個繼承體系里面只有一個這樣的成員。無論派生出多少個派生類,都只有一個static成員實例
在這里插入圖片描述


七、多繼承及其菱形繼承問題

7.1 繼承模型

在這里插入圖片描述


單繼承和多繼承
在這里插入圖片描述


菱形繼承: 會出現 二義性 和 數據冗余 的問題
在這里插入圖片描述


在這里插入圖片描述


7.2 虛繼承

為了解決菱形繼承的兩個問題,這里使用虛繼承,也就是在開始繼承相同的基類的派生類后面加上virtual再加繼承方式和基類
在這里插入圖片描述在這里插入圖片描述


我們可以設計出多繼承,但是不建議設計出菱形繼承,因為菱形虛擬繼承以后,無論是使用還是底層都會復雜很多。當然有多繼承語法支持,就一定存在會設計出菱形繼承,像Java是不支持多繼承的,就避開了菱形繼承
在這里插入圖片描述
在這里插入圖片描述


7.3 IO庫中的菱形虛擬繼承

在這里插入圖片描述


八、繼承和組合

在這里插入圖片描述


在這里插入圖片描述


九、整體源代碼

代碼如下(示例):

#include<iostream>
using namespace std;//class Student
//{
//public:
//	// 進?校園/圖書館/實驗室刷?維碼等?份認證
//	void identity()
//	{
//		// ...
//	}
//	// 學習
//	void study()
//	{
//		// ...
//	}
//protected:
//	string _name = "peter"; // 姓名
//	string _address; // 地址
//	string _tel; // 電話
//	int _age = 18; // 年齡
//	int _stuid; // 學號
//};
//class Teacher
//{
//public:
//	// 進?校園/圖書館/實驗室刷?維碼等?份認證
//	void identity()
//	{
//		// ...
//	}
//	// 授課
//	void teaching()
//	{
//		//...
//	}
//protected:
//	string _name = "張三"; // 姓名
//	int _age = 18; // 年齡
//	string _address; // 地址
//	string _tel; // 電話
//	string _title; // 職稱
//};
//int main()
//{
//	return 0;
//}//class Person
//{
//public:
//	// 進?校園/圖書館/實驗室刷?維碼等?份認證
//	void identity()
//	{
//		cout << "void identity()" << _name << endl;
//	}
//protected:
//	string _name = "張三";  // 姓名
//	string _address;       // 地址
//	string _tel;           // 電話
//	int _age = 18;         // 年齡
//};
//class Student : public Person
//{
//public:
//	// 學習
//	void study()
//	{
//		// ...
//	}
//protected:
//	int _stuid; // 學號
//};
//class Teacher : public Person
//{
//public:
//	// 授課
//	void teaching()
//	{
//		//...
//	}
//protected:
//	string title; // 職稱
//};
//int main()
//{
//	Student s;
//	Teacher t;
//	s.identity();
//	t.identity();
//	return 0;
//}// 實例演?三種繼承關系下基類成員的各類型成員訪問關系的變化
//class Person
//{
//public:
//	void Print()
//	{
//		cout << _name << endl;
//	}
//protected:
//	string _name; // 姓名
//private:
//	int _age; // 年齡
//};
//
////class Student : protected Person
////class Student : private Person
//class Student : public Person
//{
//protected:
//	int _stunum; // 學號
//};#include<vector>
#include<stack>
//namespace ming
//{//template<class T>//class vector//{};// stack和vector的關系,既符合is-a,也符合has-a
//	template<class T>
//	class stack : public std::vector<T>
//	{
//	public:
//		void push(const T& x)
//		{
//			// 基類是類模板時,需要指定?下類域,
//			// 否則編譯報錯:error C3861: “push_back”: 找不到標識符
//			// 因為stack<int>實例化時,也實例化vector<int>了
//// 但是模版是按需實例化,push_back等成員函數未實例化,所以找不到
//			vector<T>::push_back(x);
//			//push_back(x);
//		}
//		void pop()
//		{
//			vector<T>::pop_back();
//		}
//		const T& top()
//		{
//			return vector<T>::back();
//		}
//		bool empty()
//		{
//			return vector<T>::empty();
//		}
//	};
//}
//int main()
//{
//	ming::stack<int> st;
//	st.push(1);
//	st.push(2);
//	st.push(3);
//	while (!st.empty())
//	{
//		cout << st.top() << " ";
//		st.pop();
//	}
//	return 0;
//}
//
//class Person
//{
//protected:
//	string _name; // 姓名
//	string _sex; // 性別
//	int _age; // 年齡
//};
//class Student : public Person
//{
//public:
//	int _No; // 學號
//};
//int main()
//{
//	Student sobj;
//	// 1.派?類對象可以賦值給基類的指針/引?
//	Person* pp = &sobj;
//	Person& rp = sobj;
//	// ?類對象可以賦值給基類的對象是通過調?后?會講解的基類的拷?構造完成的
//	Person pobj = sobj;
//	//2.基類對象不能賦值給派?類對象,這?會編譯報錯
//	sobj = pobj;
//	return 0;
//}// Student的_num和Person的_num構成隱藏關系,可以看出這樣代碼雖然能跑,但是?常容易混淆
//class Person
//{
//protected:
//	string _name = "?李?"; // 姓名
//	int _num = 111; // ?份證號
//};
//class Student : public Person
//{
//public:
//	void Print()
//	{
//		cout << " 姓名:" << _name << endl;
//		cout << " ?份證號:" << Person::_num << endl;
//		cout << " 學號:" << _num << endl;
//	}
//protected:
//	int _num = 999; // 學號
//};
//int main()
//{
//	Student s1;
//	s1.Print();
//	return 0;
//};
//
//class A
//{
//public:
//	void fun()
//	{
//		cout << "func()" << endl;
//	}
//};
//class B : public A
//{
//public:
//	void fun(int i)
//	{
//		cout << "func(int i)" << i << endl;
//	}
//};
//int main()
//{
//	B b;
//	b.fun(10);
//	b.fun();
//	return 0;
//};//class Person
//	 {
//public:
//	Person(const char* name = "peter")
//		: _name(name)
//		 {
//		cout << "Person()" << endl;
//	}
//	Person(const Person& p)
//		: _name(p._name)
//	{
//		cout << "Person(const Person& p)" << endl;
//	}
//	Person& operator=(const Person& p)
//	{
//		cout << "Person operator=(const Person& p)" << endl;
//		if (this != &p)
//			_name = p._name;
//		return *this;
//	}
//	~Person()
//	{
//		cout << "~Person()" << endl;
//	}
//	 protected:
//		 string _name; // 姓名
//};
//class Student : public Person
//{
//public:
//	Student(const char* name, int num)
//		: Person(name)
//		, _num(num)
//	{
//		cout << "Student()" << endl;
//	}
//	Student(const Student& s)
//		: Person(s)
//		, _num(s._num)
//	{
//		cout << "Student(const Student& s)" << endl;
//	}
//	Student& operator = (const Student& s)
//	{
//		cout << "Student& operator= (const Student& s)" << endl;
//		if (this != &s)
//		{
//			// 構成隱藏,所以需要顯?調?
//			Person::operator =(s);
//			_num = s._num;
//		}
//		return *this;
//	}
//	~Student()
//	{
//		cout << "~Student()" << endl;
//	}
//protected:
//	int _num; //學號
//};
//int main()
//{
//	Student s1("jack", 18);
//	Student s2(s1);
//	Student s3("rose", 17);
//	s1 = s3;
//	return 0;
//}// C++98
//class Person
//{
//private:
//	Person(string name = "Peter")
//		:_name(name)
//	{}
//};
//
//// C++11
//class Person final
//{
//public:
//	Person(string name = "Peter")
//		:_name(name)
//	{}
//	~Person()
//	{
//		cout << "基類析構" << endl;
//	}
//};
//
//class Student;
//class Person
//{
//public:
//	friend void Display(const Person& p, const Student& s);
//protected:
//	string _name; // 姓名
//};
//class Student : public Person
//{
//protected:
//	int _stuNum; // 學號
//};
//void Display(const Person& p, const Student& s)
//{
//	cout << p._name << endl;
//	cout << s._stuNum << endl;
//}
//int main()
//{
//	Person p;
//	Student s;
//	// 編譯報錯:error C2248: “Student::_stuNum”: ?法訪問 protected 成員
//	// 解決?案:Display也變成Student 的友元即可
//	Display(p, s);
//	return 0;
//}//class Person
//{
//public:
//	string _name;
//	static int _count;
//};
//int Person::_count = 0;
//class Student : public Person
//{
//protected:
//	int _stuNum;
//};
//int main()
//{
//	Person p;
//	Student s;
//	// 這?的運?結果可以看到?靜態成員_name的地址是不?樣的
//	// 說明派?類繼承下來了,?派?類對象各有?份
//	cout << &p._name << endl;
//	cout << &s._name << endl;
//	// 這?的運?結果可以看到靜態成員_count的地址是?樣的
//	// 說明派?類和基類共?同?份靜態成員
//	cout << &p._count << endl;
//	cout << &s._count << endl;
//	// 公有的情況下,?派?類指定類域都可以訪問靜態成員
//	cout << Person::_count << endl;
//	cout << Student::_count << endl;
//	return 0;
//}//class Person
//{
//public:
//	string _name; // 姓名
//};
//class Student : public Person
//{
//protected:
//	int _num; //學號
//};
//class Teacher : public Person
//{
//protected:
//	int _id; // 職?編號
//};
//class Assistant : public Student, public Teacher
//{
//protected:
//	string _majorCourse; // 主修課程
//};
//int main()
//{
//	// 編譯報錯:error C2385: 對“_name”的訪問不明確
//	Assistant a;
//	a._name = "peter";
//	// 需要顯?指定訪問哪個基類的成員可以解決?義性問題,但是數據冗余問題?法解決
//	a.Student::_name = "xxx";
//	a.Teacher::_name = "yyy";
//	return 0;
//}//class Person
//{
//public:
//	string _name; // 姓名
//	/*int _tel;
//	* int _age;
//string _gender;
//string _address;*/
//// ...
//};
//// 使?虛繼承Person類
//class Student : virtual public Person
//{
//protected:
//	int _num; //學號
//};
//// 使?虛繼承Person類
//class Teacher : virtual public Person
//{
//protected:
//	int _id; // 職?編號
//};
//// 教授助理
//class Assistant : public Student, public Teacher
//{
//protected:
//	string _majorCourse; // 主修課程
//};
//int main()
//{
//	// 使?虛繼承,可以解決數據冗余和?義性
//	Assistant a;
//	a._name = "peter";
//	return 0;
//}class Person
{
public:Person(const char* name):_name(name){}string _name; // 姓名
};
class Student : virtual public Person
{
public:Student(const char* name, int num):Person(name), _num(num){}
protected:int _num; //學號
};
class Teacher : virtual public Person
{
public:Teacher(const char* name, int id):Person(name), _id(id){}
protected:int _id; // 職?編號
};
// 不要去玩菱形繼承
class Assistant : public Student, public Teacher
{
public:Assistant(const char* name1, const char* name2, const char* name3):Person(name3), Student(name1, 1), Teacher(name2, 2){}
protected:string _majorCourse; // 主修課程
};
int main()
{// 思考?下這?a對象中_name是"張三", "李四", "王五"中的哪?個?Assistant a("張三", "李四", "王五");return 0;
}template<class CharT, class Traits = std::char_traits<CharT>>
class basic_ostream : virtual public std::basic_ios<CharT, Traits>
{};
template<class CharT, class Traits = std::char_traits<CharT>>
class basic_istream : virtual public std::basic_ios<CharT, Traits>
{};// Tire(輪胎)和Car(?)更符合has-a的關系
class Tire {
protected:string _brand = "Michelin"; // 品牌size_t _size = 17; // 尺?
};
class Car {
protected:string _colour = "??"; // 顏?string _num = "陜ABIT00"; // ?牌號Tire _t1; // 輪胎Tire _t2; // 輪胎Tire _t3; // 輪胎Tire _t4; // 輪胎
};
class BMW : public Car {
public:void Drive() { cout << "好開-操控" << endl; }
};
// Car和BMW/Benz更符合is-a的關系
class Benz : public Car {
public:void Drive() { cout << "好坐-舒適" << endl; }
};
template<class T>
class vector
{};
// stack和vector的關系,既符合is-a,也符合has-a
template<class T>
class stack : public vector<T>
{};
template<class T>
class stack
{
public:vector<T> _v;
};
int main()
{return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/93249.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/93249.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/93249.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

佳能iR-ADV C5560復印機如何掃描文件到電腦

打印機與電腦連接首先&#xff0c;確保佳能iR-ADV C5560復印機通過USB或Wi-Fi等網絡連接的方式成功連接到電腦。這可以通過USB線纜或Wi-Fi等網絡來實現。連接完成后&#xff0c;便可利用打印機內置的掃描功能&#xff0c;輕松將文件掃描并傳輸至電腦中。【掃描操作步驟】接下來…

騰訊AI IDE

1.官網說明&#xff1a;打開騰訊AI IDE官網。2.安裝說明&#xff1a;安裝成功后的界面。3.登錄 說明&#xff1a;通過郵箱和密碼登錄。4.成功說明&#xff1a;成功登錄如下界面。5.簡單一問說明&#xff1a;理解能力感覺不錯。擁有Claude-3.7-Sonnet??&#xff0c;??Claude…

【LeetCode 熱題 100】(一)哈希

1. 兩數之和 class Solution {public int[] twoSum(int[] nums, int target) {int length nums.length;// 1.聲明一個hashmap {nums[i], i}HashMap<Integer, Integer> map new HashMap<>();for (int i 0; i < length; i) {int second target - nums[i];if(m…

PMOS快速關斷電路、PMOS加速關斷電路

[電源系列]二、低成本MOS快速關斷電路原理分析 MOS的減速加速電路設計 分享一個微碧在網上看到的電路情況 加速電路1 PMOS關斷時間較長。 當用100kHz的頻率驅動PMOS時&#xff0c;PMOS G極的電壓信號并不是一個脈沖波&#xff0c;PMOS一直處于線性放大的狀態&#xff0c;并且…

Docker筆記(基本命令、掛載本地gpu、Dockerfile文件配置、數據掛載、docker換源)

Docker 主要用于環境搭建以及服務部署 基本命令 1.查看鏡像 docker images 2.查看容器 docker ps # 查看容器僅僅為查看運行狀態的容器 docker ps -a # 查看所有狀態的容器3.退出容器 exit4.刪除鏡像、容器 docker rm 鏡像ID docker rm 容器ID docker rm -f 容器ID # 強制刪除…

算法競賽階段二-數據結構(37)數據結構循環鏈表模擬實現

之前單鏈表中&#xff0c;數組全初始化為0&#xff0c;末尾最后一個next 存的就是0&#xff0c;指向的就是頭節點循環鏈表的基本概念循環鏈表是一種特殊的鏈表&#xff0c;其尾節點的指針域指向頭節點&#xff0c;形成一個閉環。與普通單鏈表相比&#xff0c;循環鏈表的遍歷需要…

20250727讓飛凌OK3576-C開發板在Rockchip的原廠Android14下通過耳機播音

20250727讓飛凌OK3576-C開發板在Rockchip的原廠Android14下通過耳機播音 2025/7/27 23:28緣起&#xff1a;很容易知道 飛凌OK3576-C開發板 使用的聲卡芯片是 NAU88C22YG 新唐科技(NUVOTON) NAU8822LYG NAU88C22YG 新唐立體聲音頻編解碼芯片原理圖&#xff1a;OK3576-C V1.2_202…

正向代理和反向代理的理解

**正向代理&#xff08;Forward Proxy&#xff09;和反向代理&#xff08;Reverse Proxy&#xff09;**是兩種不同類型的代理服務器&#xff0c;它們在數據傳輸過程中扮演的角色、使用場景以及工作方式都有所不同。 正向代理&#xff08;Forward Proxy&#xff09; 定義與作用&…

Java 后端 Cookie Session Token會話跟蹤技術

概述 會話從字面理解就是"兩方交流"&#xff0c;那問題就來了&#xff0c;HTTP&#xff08;超文本傳輸協議&#xff09;里面的"傳輸"不就包含了"兩方交流"的意思嗎&#xff1f;為什么要多此一舉提出會話技術呢&#xff1f; 談到這個&#xff0c;…

智譜AI GLM大模型 GLM-4-Plus的快速使用 ChatOpenAI類來調用GLM-4模型

智譜AIGLM-4&#xff0c;2024年1月16日發布的第四代基座大模型&#xff0c;其整體性能相較前代提升近60%&#xff0c;多維度指標逼近OpenAI的GPT-4水平。該模型支持128K上下文窗口&#xff08;約300頁文本處理能力&#xff09;&#xff0c;在長文本信息處理中實現100%精度召回。…

AsyncLocal淺復制的問題解決方案

針對C#中AsyncLocal<T>淺復制問題&#xff0c;以下是幾種主要的解決方案&#xff1a; 1. 使用不可變對象&#xff08;推薦&#xff09; 將存儲在AsyncLocal<T>中的對象設計為不可變的&#xff0c;避免修改共享狀態&#xff1a; public class ImmutableUserContext …

IIS發布.NET9 API 常見報錯匯總

記錄工作過程中發現的IIS常見錯誤。 1. HTTP Error 500.19 - Internal Server Error .NET 9 API --》vs打包方式如下&#xff1a; 發布到IIS后報錯HTTP Error 500.19 - Internal Server Error。 解決方案&#xff1a; 下載ASP.NET Core Hosting Bundle&#xff08;ASP.NET Co…

Google Chrome V8< 13.7.120 沙箱繞過漏洞

【嚴重】Google Chrome V8< 13.7.120 沙箱繞過漏洞 漏洞描述 V8 是 Google 開發的一款開源高性能 JavaScript 和 WebAssembly 引擎&#xff0c;廣泛用于 Chrome 瀏覽器和 Node.js 等項目中。 受影響版本中&#xff0c;JsonParser::MakeString 函數在處理長度為 1 的轉義字…

基于Spring Boot和Vue電腦維修平臺整合系統的設計與實現

用戶&#xff1a;注冊&#xff0c;登錄&#xff0c;在線報修&#xff0c;維修接單&#xff0c;維修報告&#xff0c;維修評價&#xff0c;個人資料維修工&#xff1a;登錄&#xff0c;在線報修&#xff0c;維修接單&#xff0c;維修報告&#xff0c;維修評價&#xff0c;通知公…

InsightFace(RetinaFace + ArcFace)人臉識別項目(預訓練模型,魯棒性很好)

背景介紹 這是一個 簡單的人臉識別項目&#xff0c;用 FastApi 在本地實現&#xff0c;使用預訓練模型&#xff0c;直接可用。 新方案比之前的FaceNet強太多了&#xff0c;甚至不用數據增強等操作&#xff0c;就可以識別戴眼鏡、不戴眼鏡、歪著的人臉等。 充分證明了選型的重要…

App Inventor 2 使用 MaterialIcons 圖標字體,快捷展示專業圖標

平時布局的話&#xff0c;如果要使用圖標&#xff0c;一般需要去找 png 圖片&#xff0c;且透明背景的。如果需要根據不同常見圖標進行變色的話&#xff0c;就需要準備多張不同樣式的圖標&#xff0c;還要考慮圖片的分辨率等等因素&#xff0c;非常的麻煩。 這時&#xff0c;如…

C語言——關于指針(逐漸清晰版)

為了更好地理解本篇文章的知識內容&#xff0c;讀者可以將以下文章作為補充知識進行閱讀 &#xff1a; C語言————原碼 補碼 反碼 &#xff08;超絕詳細解釋&#xff09;-CSDN博客 C語言————二、八、十、十六進制的相互轉換-CSDN博客 C語言————斐波那契數列的理解…

SVG 在線編輯器

SVG 在線編輯器 引言 隨著互聯網技術的發展&#xff0c;矢量圖形在網頁設計和數據可視化中扮演著越來越重要的角色。SVG&#xff08;可縮放矢量圖形&#xff09;因其文件小、無限縮放不模糊的特性&#xff0c;成為了網頁設計中常用的圖形格式。SVG 在線編輯器的出現&#xff0c…

libpostproc 已經從 ffmpeg 中移除,導致編譯 ffmpeg 時沒有 libpostproc

今天編譯 ffmpeg 時突然發現 libpostproc 不見了&#xff0c;-enable-postproc 也變成了非法的選項。用搜索引擎搜索相關信息找不到一點&#xff0c;于是去 github 看。 從提交記錄可以看到 libpostproc 已經被移除了 鏈接 主線中已經看不到了 libpostproc 這個目錄了

基于 Dell PowerEdge T440 搭建的 Proxmox VE 配置 RTX 3060 顯卡直通虛擬機、切換直通

基于 Dell PowerEdge T440 搭建的 Proxmox VE 配置 RTX 3060 顯卡直通虛擬機、切換直通 文章目錄 基于 Dell PowerEdge T440 搭建的 Proxmox VE 配置 RTX 3060 顯卡直通虛擬機、切換直通 1. 前言 2. 前提條件 3. 配置步驟 3.1. 啟用 VT-d 3.2. 激活 IOMMU 3.3. 添加 VFIO 模塊 …