【C++】继承基础知识及简单应用,使用reportSingleClassLayout(在Visual Studio开发人员命令提示窗口)查看派生类详细信息

author:&Carlton

tag:C++

topic:【C++】继承基础知识及简单应用,使用reportSingleClassLayout(在Visual Studio开发人员命令提示窗口)查看派生类详细信息

website:黑马程序员C++

date:2023年7月22日


目录

概要

继承规则

对象模型

构造析构顺序

同名与静态同名成员

多继承

菱形继承

VS开发人员命令操作提示窗口


概要

继承是C++面向对象程序设计的三大特性之一(封装,继承,多态),既能有效利用已定义好的类,又允许添加之前定义的类中没有的代码,有效缩减代码量,使得程序更加简洁。

继承规则

class 子类名 : 继承方式 父类名 { };

继承方式有public,protected,private

对象模型

父类所有成员都继承,只是根据继承方式不同继承得到的成员访问权限也相应改变:

父类的私有成员子类继承,但均无法访问,需要声明友元,以下说明不包括父类私有成员

①公开继承public: 访问权限相应继承

②保护继承protected: 全定为protected

③私有继承private: 全部变为private

注:成员包括属性和函数

子类对象模型结构(具体操作步骤在本文最后一小节说明):

说明子类继承父类所有成员的例子:

cpp 复制代码
#include <iostream>
using namespace std;

class Base
{
public:
	int m_a;
protected:
	int m_b;
private:
	int m_c;
};

class Son:public Base
{
public:
	int m_d;
};

void test01()
{
	Son s1;
	cout << sizeof(s1) << endl;
}

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

构造析构顺序

先构造父类,然后构造子类,析构顺序与构造顺序相反。

源代码:

cpp 复制代码
#include <iostream>
using namespace std;

class Base
{
public:
	Base()
	{
		cout << "Base的构造函数" << endl;
	}
	~Base()
	{
		cout << "Base的析构函数" << endl;
	}
};

class Son :public Base
{
public:
	Son()
	{
		cout << "Son的构造函数" << endl;
	}
	~Son()
	{
		cout << "Son的析构函数" << endl;
	}
};

void test01()
{
	Son s1;
}

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

程序运行结果:

同名与静态同名成员

需要添加作用域,对于静态成员还能通过类访问。

Son::Base::m_b << endl;

与Base::m_b含义不同,这里是在子类Son中访问父类Base作用域下的m_b静态成员变量

cpp 复制代码
#include <iostream>
using namespace std;

class Base 
{
public:
	Base():m_a(100)//父类的初始化为100
	{

	}
	int m_a;
	void func()
	{
		cout << "Base-func()" << endl;
	}
	void func(int a)
	{
		cout << "Base-func(a)" << endl;
	}
	//子类有同名的成员函数时父类的成员函数被隐藏,无法直接使用占位参数区分,还是需要添加作用域区分
	static int m_b;
};

//静态成员变量类内声明,类外定义初始化
int Base::m_b = 100;

class Son:public Base
{
public:
	Son():m_a(200)//子类的初始化为200
	{

	}
	void func()
	{
		cout << "Son-func()" << endl;
	}
	int m_a;//有同名成员
	static int m_b;		//有静态同名成员
};
int Son::m_b = 200;


void test01()
{
	Son s1;
	cout << "子类m_a:" << s1.m_a << endl;
	cout << "父类m_a:" << s1.Base::m_a << endl;		//添加作用域
	s1.func();
	s1.Base::func();		//添加作用域
	s1.Base::func(10);
	//通过对象访问静态成员
	cout << "子类m_b:" << s1.m_b << endl;
	cout << "父类m_b:" << s1.Base::m_b << endl;
	//通过类访问静态成员
	cout << "子类m_b:" << Son::m_b << endl;
	cout << "父类m_b:" << Son::Base::m_b << endl;	//与Base::m_b含义不同,这里是在子类Son中访问父类Base作用域下的m_b静态成员变量
}

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

多继承

class 子类名 : 继承方式 父类名1,继承方式 父类名2,......{ } ;

多继承可能会带来同名成员 的问题,但在实际开发过程中这块代码可能由几个人一起做,如果大量使用多继承则出现同名成员问题时寻找作用域会很麻烦。

源代码

cpp 复制代码
#include <iostream>
using namespace std;

class Base1
{
public:
	int m_a;
};

class Base2
{
public:
	int m_b;
};

class Son :public Base1, public Base2		//继承Base1和Base2
{
	int m_c;
	int m_d;
};

void test01()
{
	cout << "sizeof(Son):" << sizeof(Son) << endl;
}

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

多继承对象模型结构(具体操作步骤见本文最后一节):

菱形继承

菱形继承:A被B、C继承,D继承B、C

解决菱形继承的两个问题:①二义性矛盾 ②资源浪费

①二义性矛盾:"孙子不知道从父1那访问爷爷的东西还是从父2那里访问"

②资源浪费:无论从父1还是从父2,得到的东西是一样的,不需要得到两次

解决方法:

①添加作用域

②使用关键字virtual虚继承

源代码:

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

/*
* 解决菱形继承的两个问题:①二义性矛盾 ②资源浪费
* ①二义性矛盾:"孙子不知道从父1那访问爷爷的东西还是从父2那里访问"
* ②无论从父1还是从父2,得到的东西是一样的,不需要得到两次
*/

class School
{
public:
	School():m_slogan("厚德载物,格物致知")
	{
		
	}
	string m_slogan;
};

class Teacher1 :virtual public School {};		//加关键字virtual,虚继承

class Teacher2 :virtual public School {};

class Student :public Teacher1, public Teacher2 {};

void test01()
{
	Student s1;
	//cout << s1.m_slogan << endl;	//有二义性错误,m_slogan是Teacher1的还是Teacher2的
	cout << s1.Teacher1::m_slogan << endl;		//通过作用域解决第一个问题:二义性错误
	cout << s1.Teacher2::m_slogan << endl;
	cout << s1.m_slogan << endl;	//使用virtual虚继承可以不加作用域,都通过虚拟指针指向基类School的m_slogan,是同一个成员变量
}

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

对象模型结构(具体操作步骤见本文最后一节):

使用虚继承前:

使用虚继承后:

vbtable:虚基类表

vb:virtual base 虚基类

ptr:pointer 指针

数字代表位移量

VS开发人员命令操作提示窗口

系统菜单里找到:

跳转盘符:

锁定文件路径(包含源文件的上一级目录):

应用:

①查看该文件路径下文件情况

②查看类对象模型结构

欢迎指正与分享,谢谢!

相关推荐
过过过呀Glik几秒前
在 Ubuntu 上安装 Muduo 网络库的详细指南
linux·c++·ubuntu·boost·muduo
蜀黍@猿1 小时前
【C++ 基础】从C到C++有哪些变化
c++
Am心若依旧4091 小时前
[c++11(二)]Lambda表达式和Function包装器及bind函数
开发语言·c++
zh路西法1 小时前
【C++决策和状态管理】从状态模式,有限状态机,行为树到决策树(一):从电梯出发的状态模式State Pattern
c++·决策树·状态模式
轩辰~1 小时前
网络协议入门
linux·服务器·开发语言·网络·arm开发·c++·网络协议
lxyzcm2 小时前
C++23新特性解析:[[assume]]属性
java·c++·spring boot·c++23
蜀黍@猿2 小时前
C/C++基础错题归纳
c++
雨中rain2 小时前
Linux -- 从抢票逻辑理解线程互斥
linux·运维·c++
ALISHENGYA3 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法
arong_xu3 小时前
现代C++锁介绍
c++·多线程·mutex