c++学习笔记(13)

继承方式

class b : public a
class b : protected a
class b : private a

父类的私有属性,无论哪种继承方式,都无法访问
公共继承:父类的属性继承到子类时,是不变的
保护权限:都会变为保护权限
私有继承:都会变为私有权限

继承中的对象模型

class base
{
public:
	int m_a;
protected:
	int m_b;
private:
	int m_c;	
};
class son : public base
{
public:
	int m_d;
}

cout<<sizeof(son)<<endl;

子类最终有十六个字节,父类中所有的非静态属性都会被继承,包括私有属性,只是无法访问

利用开发人员命令提示工具查看对象模型
跳转盘符
跳转文件路径 cd 具体路径下
查看别名
c1 /d1 reportSingleClassLayout类名 文件名
用于查看对象的具体内容

继承中构造和析构的顺序

当子类继承父类时,当创建子类对象,也会调用父类的构造函数

先调用父类的构造函数,后调用父类的析构函数

继承同名成员的处理方式

访问子类同名成员,直接访问即可
访问父类的同名成员,需要加作用域

//构建父类对象base,属性m_a = 100,func()
//构建子类对象son,属性m_a = 200,func()
son s;
cout<<s.m_a<<endl;
//访问子类中的属性
cout<<s.base::m_a<<endl;
//加入作用域,访问父类中的属性
s.func();
//调用子类函数
s.base::func()//加入作用域,调用父类成员函数

如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中的所有同名成员函数
(即使父类的成员函数输入值与子类不同可以区分,也无法直接调用)

同名静态成员处理

通过对象来访问和非静态成员处理方式一致

//通过类名来访问
cout<<son::m_a<<endl;
cout<<son::base::m_a<<endl
//通过son类名来访问父类作用域下的属性
son::func();
son::base::func();

多继承语法
c++允许一个类继承多个类
语法:class 子类 :继承方法 父类1 ,继承方式 父类2

多继承可能会引发父类中有成名出现,需要加作用域区分

菱形继承

两个派生类继承同一个基类
又有某个类同时继承着两个派生类
这种继承被称为菱形继承,或者钻石继承

存在问题:
最终的类,继承了两份基类的属性,只需要一份即可
最终的类使用数据时,会出现二义性

利用虚继承解决
继承之前 加上关键字virtual变为虚继承
这样的父类称为虚基类

发生虚继承之后,相当于共享了基类的数据,这样就不会出现二义性,和数据重复

多态
多态分为两类:
静态多态:函数重载和运算符重载属于静态多态,复用函数名
动态多态:派生类和虚函数实现运行时多态
区别:
静态多态的函数地址早绑定 编译使其确定函数地址
动态多态的函数地址晚绑定 运行阶段确定函数地址

//构建animal父类,speak()函数
//构建cat子类,speak()函数
void dospeak(animal &animal)
//利用animal类型引用cat对象,c++允许父子类型转换
//在编译阶段就确定了函数的地址,所以输入的数据都会以animal数据类型处理
{
	animal.speak();
}
void test1()
{
	cat cat;
	dospeak(cat);
}
virtual void speak();
//虚函数
//将基类的的speak()函数进行修改,实现地址晚绑定,根据运行时函数的输入,去调整speak()所在的数据类型

动态多态满足条件
1.存在继承关系
2.子类要重写父类中的虚函数
重写:函数返回值的类型 函数名 参数列表 完全相同

动态多态的使用
父类的指针或者引用执行子类对象

原理:当父类构建虚函数时,类内部储存了vfptr(虚函数表指针)指向vftable(虚函数表),内部储存着虚函数,当构建子类时,子类中会也存在vfptr,但是地址不同,内部储存着父类的虚函数,但是当子类重写虚函数时,内部会被替换为子类的虚函数
当父类的指针或者引用指向子类对象时,发生多态

animal & animal = cat;
//指针指向cat,会去调用子类中的虚函数
animal.speak();

多态练习

class abstractcalculator
{
public:
	virtual int getresult()
	{
		return 0;
	}
	int m_num1;
	int m_num2;
}

class add:public abstractcalculator
{
public:
	virtual int getresult()
	{
		return m_num1+m_num2;
	}
}

class sub:public abstractcalculator
{
public:
	virtual int getresult()
	{
		return m_num1-m_num2;
	}
}
void test()
{
	abstractcalculator * abs = new add;
	abs->m_num1 = 10;
	abs->m_num2 = 20;
	abs->getresult();
	delete abs;
	//本质是释放了堆区的数据,而不是删除指针
}

多态的写法有助于后期功能拓展,并且不需要修改源码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值