前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >c++继承知识详解(一)

c++继承知识详解(一)

作者头像
洁洁
发布2023-10-10 14:05:49
1400
发布2023-10-10 14:05:49
举报
文章被收录于专栏:小洁叫你mysql

继承好处: 减少重复的代码 语法: class 子类(派生类):继承方式 父类(基类) 继承方式: 公共继承,保护继承,私有继承

代码语言:javascript
复制
#include<iostream>
using namespace std;
/*
class baise  
{
public:
	int ma;
protected:
	int mb;
private:
	int mc;
};
//定义一个父类,里面有3种
//儿子以公共方式继承父类
class son :public baise
{
//注意:
	//父类中所有非静态成员属性会被子类继承下去
	//父类中私有成员属性是被编译器·隐藏起来了,但是确实是被继承下来了
	int mb;
	void fun()
	{
		ma = 100; // 父类公共内容  以公共继承方式,类内 类外可以访问,也是公共权限
		mb = 100; // 父类保护内容  以公共继承方式,类内可以访问,类外不能访问,也是保护权限
		//mc = 100;父类的私有内容,以公共继承方式,访问不到
	}
};
void test01()
{
	son s1;
	s1.ma = 100;
	//s1.mb = 100; 保护权限,类外不能访问

	cout << sizeof(s1) << endl;
}

//以保护权限来继承父类

代码语言:javascript
复制
class son2 :protected baise
{
	void func()
	{
		ma = 100;//父类公共内容  以保护继承方式,类内可以访问,类外不能,是保护权限
		mb = 100; //父类保护内容  以保护继承方式,类内可以访问,类外不能,是保护权限
		//mc = 100;父类的私有内容,以保护继承方式,访问不到
	}
};
void test02()
{
	son2 s2;
	//以保护权限继承,类外都不能访问
	/*s2.ma = 100;
	* s2.mb=100;
	*/
/*
}

//以私有权限继承父类
class son3 :private baise
{
	void func()
	{
		ma = 100;//父类公共内容  以私有继承方式,类内可以访问,类外不能,是私有权限
		mb = 100; //父类保护内容  以私有继承方式,类内可以访问,类外不能,是私有权限
		//mc = 100;父类的私有内容,以保护继承方式,访问不到
	}
};
void test03()
{
	son3 s3;
	//s2.ma = 100;
	//s2.mb=100;

}
*/

//继承中同名成员处理

代码语言:javascript
复制
class base
{
public:
	base()
	{
		ma = 100;
	}
	int ma;
};
class sonn :public base
{
public:
	sonn()
	{
		ma = 10;
	}
	int ma;
};
//同名成员
void testt()
{
	sonn s;
	cout << "子类中的成员.访问" << s.ma << endl;
	cout << "父类中的成员base::作用域访问" << s.base::ma << endl;
}

//同名函数

  • 如果子类中没有,只有父类中有,直接调用会调用父类中的函数
  • 直接调用,调用的·是子类中同名的成员
  • 如果子类中出现与父类同名的成员函数,会隐藏掉父类中所有同名的函数,除非加上作用域
  • 总结:
  • 子类对象可以直接访问到子类中的同名成员
  • 子类对象加作用域可以访问到父类中同名的成员
  • 当子类和父类有同名的成员函数时,子类会隐藏父类中同名成员函数,,加作用域可以访问到父类中同名的函数

//同名静态成员处理 //同名静态成员属性

代码语言:javascript
复制
class person
{
public:
	static int ma;
	static void func()
	{
		cout << "person的成员函数的调用" << endl;
	}
	static void func(int a)
	{
		cout << "person(int a)的成员函数的调用" << endl;
	}
};
int person::ma = 100;
class personson :public person
{
public:
	static int ma;
	static void func()
	{
		cout << "personson的成员函数的调用" << endl;
	}
};

int personson::ma = 200;

void test01()
{
	//1.通过对象访问
	cout << "1.通过对象访问" << endl;
	personson p; //实例化
	cout <<"personson下:"<< p.ma << endl;
    cout << "person下"<<p.person::ma << endl;
	
	//2.通过类名访问
	cout << "2.通过类名访问" << endl;
	//第一个::代表通过类名方式访问
	//第二个::代表访问父类作用域下
	cout<<"person下"<< personson::person::ma << endl;
	cout<<"personson下" << personson::ma << endl;
}

//同名静态成员函数

代码语言:javascript
复制
void test02()
{
	//通过对象访问
	personson p;
	p.func();
	p.person::func();

	//通过类名方式访问
	personson::person::func();
	personson::func();
	//错误personson::func(10); 在personson下没有类似void func(int a)的函数
	personson::person::func(10);
}

//多继承语法 语法:class 子类:继承方式 父类1,继承方式 父类2,…

  • 多继承中如果父类中出现了同名的情况,子类中使用的时候要加作用域来区分
代码语言:javascript
复制
class base1
{
public:
	base1()
	{
		ma = 100;

	}
	int ma;
};
class base2
{
public:
	base2()
	{
		mb = 200;
		ma = 200;
	}
	int mb;
	int ma;
};

//现在要有一个子类,来继承base1 base2

代码语言:javascript
复制
class base3 :public base1, public base2
{
public:
	base3()
	{
		mc = 300;
		md = 400;
	}
	int mc;
	int md;
};
void test03()
{
	base3 b;
	cout << sizeof(b) << endl;
	//错误-》因为名字重复要用作用域加以区分cout << b.ma << endl;
	cout << "base1下" << b.base1::ma << endl;
	cout << "base2下" << b.base2::ma << endl;
}

//利用虚继承可以解决 菱形继承问题 //主要带来问题是子类继承两份相同的数据,导致资源浪费以及毫无意义

代码语言:javascript
复制
class animal
{
public:
	int age;
};
//加入virtual后变成虚继承,animal叫虚基类
//从而统一
class monkey:virtual public animal{};
class xingxing:virtual public animal{};
//不管猴子还是猩猩,都是动物,所以虚继承animal类
class persons:public monkey,public xingxing{};
/*
* 对象模型:
* class persons   size(8):
        +---
 0      | +--- (base class monkey)
 0      | | +--- (base class animal)
 0      | | | age
        | | +---
        | +---
 4      | +--- (base class xingxing)
 4      | | +--- (base class animal)
 4      | | | age
        | | +---
        | +---
        +---
*/


//虚继承之后对象模型:
/*
* class persons   size(12):
        +---
 0      | +--- (base class monkey)
 0      | | {vbptr}
        | +---
 4      | +--- (base class xingxing)
 4      | | {vbptr}
        | +---
        +---
        +--- (virtual base animal)
 8      | age
        +---

persons::$vbtable@monkey@:
 0      | 0
 1      | 8 (personsd(monkey+0)animal)

persons::$vbtable@xingxing@:
 0      | 0
 1      | 4 (personsd(xingxing+0)animal)
vbi:       class  offset o.vbptr  o.vbte fVtorDisp
          animal       8       0       4 0
*/

/*

  • 解释:
  • vbptr 虚基类指针
  • v代表 virtual
  • b 代表 base
  • ptr 代表 pointer
  • 8 | age
  • 0 | ±-- (base class monkey) 0 | | {vbptr} persons::$vbtable@monkey@: 0 | 0 1 | 8 (personsd(monkey+0)animal)

偏移量是8 0+8=8

4 | ±-- (base class xingxing) 4 | | {vbptr} persons::$vbtable@xingxing@: 0 | 0 1 | 4 (personsd(xingxing+0)animal)

偏移量是4 4+4=8 所以会找到同一个数据,只有一份 */

代码语言:javascript
复制
void test04()
{
	persons p;
	p.monkey::age = 100;//monkey::作用域下
	p.xingxing::age = 200;//xingxing::作用域下
	cout << p.monkey::age << endl;
	cout << p.xingxing::age << endl;
	cout << p.age << endl;
}
代码语言:javascript
复制
int main()
{
	//testt();
	//test01();
	//test02();
	//test03();
	test04();
	system("pause");
	return 0;
}

当父类中有保护权限,私有权限时,会继承到子类中吗? 按道理来说,父类中所有非静态成员属性会被子类继承下去,所以父类中私有成员属性确实是被继承下来了,但是被编译器隐藏起来了。

可以利用开发命令提示工具查看对象·模型 (更清晰,明了) 首先先跳转到该位置的盘 比如 D:盘等 cd 到指定具体位置下的文件路径(看自己写的文件名) 输入 cl /d1 reportSingleClassLayout类名 文件名

最后说明一下: 继承中构造和析构的顺序是?: 先构造父类,再构造子类 先析构子类,再析构父类

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-07-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档