虚函数,虚继承,纯函数继承

覆盖

覆盖就是子类会覆盖与父类相同的虚函数,下来看一个覆盖的代码:

class A
{
public:
	void virtual f()
	{
		cout << "A" << endl;
	}
};

class B :public A
{
public:
	void virtual f()
	{
		cout << "B" << endl;
	}
};

int main()
{
	A* pa = new A();
	pa->f();    //A
	B* pb = (B*)pa;
	pa->f();   // A
	
	delete pa, pb;
	pa = new B();
	pa->f();   //B
	pb = (B*)pa;
	pb->f();   //B
	return 0;
}

这是一个虚函数覆盖虚函数的问题,A中f是一个虚函数,虚函数是被子类同名函数所覆盖的。送一A类中的f函数会被B类中的f函数覆盖。很明显第一个输出是输出“A”,但是在 B* pb = (B*)pa;里面,该语句的意思是转化pa为B类型并新建一个pb指针,将pa赋值到pb,所以pa在这里是没有发生任何变化的,所以第二个pa->f也指向的是“A”。

delete pa,pb删除了pa,pb指向的地址,但pa,pb指针并没有被删除,这就是野指针(悬浮指针),现在重新指向B类,而pa指针类型是A类的,父类的指针指向子类的对象,在这里就会发生覆盖。第三个打印的是“B”.pb=(B*)pa;转化pa为B类指针给pb赋值,但pa所指向的f函数是B类的f函数,所以pb所指向的f函数是B类的f函数,打印“B”。

虚继承

虚继承是多重继承中特有的概念,虚基类是为了解决多重继承而出现的。例如B继承A,C继承A,D同时继承BC,因此出现了交叉继承,在D类中会出现两个A,为了节省空间,可以将B,C对A的继承定义为虚拟继承,而A就成了虚基类,这就是所谓的菱形继承。

class A;
class B :public virtual A;
class C :public virtual A;
class D :public B, public C;

虚函数继承

下面看一段代码:

class A
{
public:
	virtual void a()
	{}
};
class B :public virtual A
{

public:
	virtual void b()
	{}
};
class C:public virtual A
{
public:
	virtual void c()
	{}
};
int main()
{
	cout << sizeof(A) << endl;   // 4
	cout << sizeof(B) << endl;   // 12
	cout << sizeof(C) << endl;   // 20
	return 0;  
}

A类中有一个虚函数,所以必须有一个对应的虚函数表来记录对应的函数入地址。所以有虚函数的类生成对象的前四个字节是一个指针,指向的是虚函数生成的虚函数表,所以A类的大小是4个字节。

对于B类,虚继承了A类,同时还拥有自己的系函数,那么B类有一个B类vfptr指针指向自己的虚函数表,这里大小是4个字节。可虚继承需要通过加入一个虚类指针记为vfptr_B_A来指向父类,这里大小也是4个字节,同时还有继承父类的所有内容sizeof(A)是4个字节大小,所以B类的大小是12个字节。

C类的话也有一个自己的vfptr_C指向自己的虚函数表,然后是一个虚类指针vfptr_C_B_A,同时还继承了B类的所有内容,所以大小是12字节+4+4 = 20字节。

这就是虚函数继承,虚继承不仅继承了所有父类内容,还有一个虚类指针来指向父类。这里的大小是在gcc编译下的结果,如果父类有一个指向自己虚函数的指针,会和子类共享这个父类的虚函数表的空间,不会占用子类的内存。在VC条件下编译不共享这个虚函数指针空间

纯虚函数

看下面代码有什么问题?

class A
{
public:
	A()
	{}
	~A()
	{}
	virtual void f() = 0;
};

int main()
{
	A a;

	return 0;
}

这个代码的问题出在A a;这里,因为A类中的f函数是一个纯虚函数,所以A类不能实例化对象。解决方法是将f()函数修改成一般函数。

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值