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

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

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

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

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;

}
*/

//继承中同名成员处理

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

//同名函数

  • 如果子类中没有,只有父类中有,直接调用会调用父类中的函数

  • 直接调用,调用的·是子类中同名的成员

  • 如果子类中出现与父类同名的成员函数,会隐藏掉父类中所有同名的函数,除非加上作用域

  • 总结:

  • 子类对象可以直接访问到子类中的同名成员

  • 子类对象加作用域可以访问到父类中同名的成员

  • 当子类和父类有同名的成员函数时,子类会隐藏父类中同名成员函数,,加作用域可以访问到父类中同名的函数

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

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

//同名静态成员函数

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,…

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

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

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

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

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

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
所以会找到同一个数据,只有一份
*/

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;
}
int main()
{
	//testt();
	//test01();
	//test02();
	//test03();
	test04();
	system("pause");
	return 0;
}

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

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

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

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洁洁!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值