码迷,mamicode.com
首页 > 其他好文 > 详细

【探索】VS下虚继承实现的方法-1

时间:2016-03-12 06:56:04      阅读:244      评论:0      收藏:0      [点我收藏+]

标签:vs.菱形继承.原理.c++

    C++的虚继承主要解决了数据冗余与二义性的问题,起实现方法是什么呢,我们先看一段代码。

#include<iostream>
using namespace std;
class A
{
public:
	int _num;
};
class B1 : public A
{

};
class B2 : public A
{

};
class C : public B1, public B2
{

};
int main()
{
	C c;
	cout << sizeof(c) << endl;
	c.B1::_num = 1;
	c.B2::_num = 2;
	cout << "c.B1::_num:" << c.B1::_num << endl;
	cout << "c.B2::_num:" << c.B2::_num << endl;
	cout << "c._num:" << c._num << endl;
	return 0;
}

    这是一个菱形继承,直接访问两个域中的_num并赋不同值时,两个域中的_num不会是同一个数值,证明了c中含有两个_num成员变量。当我们访问C域的_num,系统无法识别到底是访问B1所继承下来的还是B2所被继承下来的,这里编译器会报错,这里c的大小为8个字节,调试点开监视窗口我们可以看到:

技术分享

一个C在不同域里继承了两份A类的成员变量,这样就造成了数据冗余及二义性。

    如何解决这个问题呢,C++中引入了关键字“vritual”在一代继承时加入关键字,修改后我们的代码为:

#include<iostream>
using namespace std;
class A
{
public:
	int _num;
};
class B1 : virtual public A
{

};
class B2 : virtual public A
{

};
class C : public B1, public B2
{

};
int main()
{
	C c;
	cout << sizeof(c) << endl;
	c.B1::_num = 1;
	c.B2::_num = 2;
	cout << "c.B1::_num:" << c.B1::_num << endl;
	cout << "c.B2::_num:" << c.B2::_num << endl;
	cout << "c._num:" << c._num << endl;
	return 0;
}

    这时我们发现通过c我们不但可以访问到自己域的成员变量,还可以访问到所继承类的成员变量,并且,当给不同域的同名成员变量赋值之后,它们的外在表现都是同一个值,这样节解决了二义性与数据冗杂,为什么说是外在表现呢,当我们打开调试窗口与内存时我们会看到:

调试窗口:

技术分享

调试窗口中,c不但包含两个父类的成员变量,还包含两个父类共同的父类的成员变量,这时c的大小为12。更惊奇的是,无论我们通过那个域名对其成员变量进行赋值,其他域的成员变量的值也会随之改变,这时为什么呢。这里我们打开内存监视窗口:

技术分享

这里我们可以看到,c中存的并不是真正的三个类中的成员变量,而是两个指针,与一个成员变量,拿着两个指针究竟指向的是什么呢,我们再打开更多的内存窗口进行观察:

第一个指针:

技术分享

第二个指针:

技术分享

    我们可以发现,这两个指针都为空,但是,在这两个指针底下,却有两个数字,这两个数字又恰好与存放这两个地址内容所在地址到存放c成员变量所在地址的偏移相同。由此可以看出VS下实现virtual关键字解决菱形继承的二义性与数据冗余的方法是,通过指针的偏移,使c中所存在的三块空间,在直接或间接的条件下,指向同一块空间。

    未完待续

本文出自 “pawnsir的IT之路” 博客,请务必保留此出处http://10743407.blog.51cto.com/10733407/1750123

【探索】VS下虚继承实现的方法-1

标签:vs.菱形继承.原理.c++

原文地址:http://10743407.blog.51cto.com/10733407/1750123

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!