【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

        注:成员包括属性和函数

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

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

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

#include 
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;
}

构造析构顺序

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

        

源代码:

#include 
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;
}

程序运行结果:

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

同名与静态同名成员

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

         Son::Base::m_b << endl;    

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

#include 
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,……{ } ;

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

源代码

#include 
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;
}

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

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

菱形继承

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


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

        解决方法:

        ①添加作用域

        ②使用关键字virtual虚继承

源代码:

#include 
#include 
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;
}

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

使用虚继承前:

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

 

使用虚继承后:

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

vbtable:虚基类表

vb:virtual base 虚基类

ptr:pointer 指针

数字代表位移量

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

系统菜单里找到:

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

跳转盘符:

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

 

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

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

 

应用:

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

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

 

        ②查看类对象模型结构

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

欢迎指正与分享,谢谢!

你可能感兴趣的:(C++,暑期实践,c++,命令模式)