c++继承与派生知识点


记录一些遗忘较快的知识,用的不多,时间久了就遗忘;后头番翻书比较费时间,记录一下

析构函数与构造函数

  1. 析构函数的调用顺序
    先执行派生类的析构函数,对派生类新增加的成员进行清理;然后调用子对象的析构函数,对子对象进行清理;最后调用基类的析构函数,对基类进行清理

  2. 基类的构造函数不能继承,在声明派生类的时候,派生类没有把基类的构造函数继承过来,因此基类成员初始化的工作也要由派生类函数承担;执行派生类构造函数的顺序为: 1)调用基类构造函数,对基类成员初始化;2)调用子对象构造函数,对子对象数据成员初始化;3)在执行派生类构造函数,对派僧类数据成员初始化

虚基类

引入虚基类的原因
当一个派生类有多个直接基类,这些直接基类又有共同的基类,那么直观上这个派生类就包含该间接基类的多份同名成员;在派生类中引用该成员的时候为了避免二义性,就必须在对象名后边添加基类名;这不仅占用了较多的空间,还增加了访问成员的困难;见下边例子的困难

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
class A1
{
public:
	int a;
	A1(int aa)
	{
		a = aa;
	}
};
class A2
{
public:
	int a;
	A2(int aa)
	{
		a = aa;
	}
};
class A3:public A1,public A2
{
public:
	int b;
	A3(int v1, int v2, int v3) :A1(v1), A2(v2)
	{
		b = v3;
	}
};

int main()
{
	A3 obj(1, 2, 3);
	cout << obj.A1::a << endl;
	return 0;
}

虚基类的作用
虚基类使得在继承共同基类的时候只留下一份成员,就是说共同的基类的对象就留下一份;
注意虚基类并不是在声明基类的时候声明的,而是在声明派生类的时候指定继承方式的时候声明的;
虚基类的构造函数,在派生类中构造函数中,以往只需要对派生类的直接基类进行初始化,但是对于虚基类的情况,最后的派生类不仅需要对直接基类进行初始化,而且需要对直接基类的共同基类进行初始化;c++编译系统只执行最后的派生类对虚基类的构造函数的调用,而忽略虚基类的其他派生类对虚函数的构造函数的调用,这就保证了虚基类的数据成员不会被多次初始化;

使用虚基类以后派生类对象就只保留了共同基类的一份数据,可以直接用品派生类对象进行引用;

基类与派生类的转换

公用派生具有基类的全部功能,所有基类能够实现的功能,子类都是实现;其他类型的继承不能实现基类的全部功能;因此只用公用派生才是基类的真正子类型

  1. 赋值兼容
    不同的数据类型之间在一定的条件下可以进行类型的转换,比如说整型数据可以转化为浮点型,这种不同类型数据之间的自动转换和赋值称为赋值加兼容
    那么基类和派生类之间也有赋值兼容的关系;
    1) 派生类对象可以向基类对象赋值
    2) 派生类对象可以替代基类对象向基类对象的引用赋值和初始化
    3) 如果函数的参数是基类对象和基类对象的引用,那么可以将子类的对象传入函数中
    4) 派生类对象的地址可以赋值给指向基类对象的指针,也就是说指向基类对象的指针可以指向派生类对象

注意
1) 子类对象可以给父类对象赋值,反之不成立
2) 指向基类对象的指针可以指向派生类对象,但是只是指向了派生类从基类继承过来的那部分;只能访问派生类中的基类成员,而不能访问派生类中增加的成员;见下例子

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
class student
{
private:
	string name;
	int score;
public:
	student(string n, int s)
	{
		name = n;
		score = s;
	}
	void display()
	{
		cout << "name:" << name << endl;
		cout << "score:" << score << endl;
		return;
	}
};

class graduate:public student
{
private:
	int wage;
public:
	graduate(string s, int n, int w) :student(s,n)
	{
		wage = w;
	}
	void dispaly()
	{
		student::display();
		cout << wage << endl;
		return;
	}
};

int main()
{
	student stu("feng haojun", 100);
	graduate gra("haojun", 100, 100000);
	student* pt = &stu;
	pt->display();
	pt = &gra;
	cout << endl;
	pt->display();
	return 0;
}
name:feng haojun
score:100

name:haojun
score:100

可见当基类对象指针指向派生类的时候,调用display函数并不是派生类中的display函数。而是基类对象中的diaplay函数;我的100k工资没有打印出来;
所以怎么样才能用这种方法把我的wage打印出来给大家看呐,就需要引用虚函数的概念这在下一篇文章介绍

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

星光技术人

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

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

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

打赏作者

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

抵扣说明:

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

余额充值