【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开发人员命令操作提示窗口

系统菜单里找到:

跳转盘符:

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

应用:

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

②查看类对象模型结构

欢迎指正与分享,谢谢!

相关推荐
lulu_gh_yu15 分钟前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
ULTRA??1 小时前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++
凌云行者1 小时前
OpenGL入门005——使用Shader类管理着色器
c++·cmake·opengl
凌云行者1 小时前
OpenGL入门006——着色器在纹理混合中的应用
c++·cmake·opengl
~yY…s<#>2 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
可均可可3 小时前
C++之OpenCV入门到提高004:Mat 对象的使用
c++·opencv·mat·imread·imwrite
白子寰3 小时前
【C++打怪之路Lv14】- “多态“篇
开发语言·c++
小芒果_013 小时前
P11229 [CSP-J 2024] 小木棍
c++·算法·信息学奥赛
gkdpjj3 小时前
C++优选算法十 哈希表
c++·算法·散列表
王俊山IT3 小时前
C++学习笔记----10、模块、头文件及各种主题(一)---- 模块(5)
开发语言·c++·笔记·学习