详细讲解虚继承

虚继承的作用:防止产生二义性

先来看一看下面的一段代码吧:

#define _CRT_SECURE_NO_WARINGS
#include<iostream>
#include<string>
using namespace std;
class Grandfather
{
public:
	Grandfather() { cout << "爷爷的构造函数" << endl; }
	~Grandfather() { cout << "爷爷的析构函数" << endl; }
};
class Father :public Grandfather
{
public:
	Father() { cout << "爸爸的构造函数" << endl; }
	~Father() { cout << "爸爸的析构函数"<<endl; }
};
class Mother :public Grandfather
{
public:
	Mother() { cout << "妈妈的构造函数" << endl; }
	~Mother() { cout << "妈妈的析构函数" << endl; }
};
class Children :public Father, public Mother
{
public:
	Children() { cout << "儿子的构造函数" << endl; }
	~Children() { cout << "儿子的析构函数" << endl; }
};
int main()
{
	Children me;
	return 0;
}

下面我们再来看一看他的输出结果:

现在我们对运行结果进行分析不难得出:执行Children时必须先执行Father类(因为Children公有继承了Father)但是往前面找到Father类我们又发现它公有继承了Grandfather类,因此最先执行的是Grandfather的构造函数,再执行Father和Mother的构造函数,最后执行自己的构造函数。析构函数的话与构造函数的顺序相反。

在这条代码的输出结果中我们发现,Children继承了两次爷爷类,这无疑会增加程序的运行时间,如果我们只想继承一次爷爷类就要使用到虚继承的知识。虚继承可以使子类只继承一次父类的父类。实现方法很简单:就是在Father和Mother继承爷爷类之前加一个virtual即可

代码:

#define _CRT_SECURE_NO_WARINGS
#include<iostream>
#include<string>
using namespace std;
class Grandfather
{
public:
	Grandfather() { cout << "爷爷的构造函数" << endl; }
	~Grandfather() { cout << "爷爷的析构函数" << endl; }
};
class  Father :virtual public Grandfather
{
public:
	Father() { cout << "爸爸的构造函数" << endl; }
	~Father() { cout << "爸爸的析构函数"<<endl; }
};
class  Mother :virtual public Grandfather
{
public:
	Mother() { cout << "妈妈的构造函数" << endl; }
	~Mother() { cout << "妈妈的析构函数" << endl; }
};
class Children :public Father, public Mother
{
public:
	Children() { cout << "儿子的构造函数" << endl; }
	~Children() { cout << "儿子的析构函数" << endl; }
};
int main()
{
	Children me;
	return 0;
}

运行结果:

为什么析构函数必须是虚函数

首先我们先来复习一下

多态的三要素:

一、要有子类继承父类

二、要有虚函数

三、父类指针指向对象

来看看这个代码:

#include<iostream>
using namespace std;
class Father
{
public:
	~Father() { cout << "父类的析构函数" << endl; }
};
class Son :public Father
{
public:
	~Son() { cout << "子类析构函数"; }
};
int main()
{
	Father* p = new Son;
	delete p;
	return 0;
}

他的运行结果:

从运行结果我们可以发现:子类的析构函数没有被调用,子类的资源内存没有被释放,这会造成内存泄漏,解决方法很简单,我们把Father类的析构函数写成虚函数即可

#include<iostream>
using namespace std;
class Father
{
public:
	virtual ~Father() { cout << "父类的析构函数" << endl; }
};
class Son :public Father
{
public:
	~Son() { cout << "子类析构函数"<<endl; }
};
int main()
{
	Father* p = new Son;
	delete p;
	return 0;
}

模板类的继承(继承子类的所有属性)

继承的遗传性(继承基类的所有属性)

#include<iostream>
using namespace std;
class A
{
public:
	A(int a):a(a){}
	int a;
};

class B:public A
{
public:
	//B需要调用A的构造函数A()
	B(int a,int b):b(b),A(a){}
	//int a; 有a的属性
	int b;
};
class C :public B
{
public:
	//C需要调用B的构造函数但是不需要调用A的构造函数
	C(int a,int b,int c):c(c),B(a,b){}
	//int a ,b;有a b 的属性
	int c;
};
class D :public C
{
public:
	//D只需要调用C的构造函数
	D(int a,int b,int c,int d):d(d),C(a,b,c){}
	//int a,b,c;有a b c的属性
	int d;

	void print()
	{
		cout << "a= " << a << " b= " << b << " c= " << c << " d= " << d << endl;
	}
};


int main()
{
	cout << "I Love You" << endl;
	D object(1, 2, 3, 4);
	object.print();
	return 0;
}

输出:

I Love You
a= 1 b= 2 c= 3 d= 4

214135

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值