“继承”是c++面向对象语言的特点之一,对于一个类,我们如果想对这个类的功能进行扩充,这就可以通过"继承"的方式重新增添或删除这个类中的某些功能。C++语言支持单继承和多继承,如果不大清楚单继承和多继承的知识,不妨先看一下我以前的博客。正是因为c++支持这两种继承方式,所以才会出现菱形继承的方式。菱形继承顾名思义就是将单继承和多继承进行结合,形成的一种继承结构。下面是简单的菱形继承的图解:
这里有4个类分别是A、B、C、D。B和C都继承类A,我们把父类A也可称为“超类”,而类D又继承了B类和C类,下面是四个类中具体所包含的成员变量和成员函数:
class A
{
public:
virtual void fun1()
{
cout << "A::fun1" << endl;
}
virtual void fun2()
{
cout << "A::fun2" << endl;
}
virtual void fun3()
{
cout << "A::fun3" << endl;
}
private:
int _a;
};
class B: public A
{
public:
virtual void fun1()
{
cout << "B::fun1" << endl;
}
virtual void fun3()
{
cout << "B::fun3" << endl;
}
private:
int _b;
};
class C : public A
{
public:
virtual void fun1()
{
cout << "C::fun1" << endl;
}
virtual void fun3()
{
cout << "C::fun3" << endl;
}
private:
int _c;
};
class D : public B, public C
{
public:
virtual void fun1()
{
cout << "D::fun1" << endl;
}
virtual void fun3()
{
cout << "D::fun3" << endl;
}
virtual void fun4()
{
cout << "D::fun4" << endl;
}
private:
int _d;
};
在vs2013上面运行,进行监视能够看出菱形继承里面的内存布局如下:
我们能够看到对象d中有继承的类B和类C,其中类B和类C中都各自包括一个虚表指针,且指针的地址是不相同的,则两个类各自存在一个虚函数表。同时我们也能够看到菱形继承中,对象d中存在两个成员_a,这就存在问题,当我们想要访问_a时,编译器也不会知道我们想要访问的是哪一个变量,这就说明菱形继承存在一个“数据冗余”和“二义性“的问题。那么如何解决菱形继承所存在的这种问题呢?
“虚拟继承”可以解决菱形继承所存在的问题。所谓虚拟继承就是增加一个虚基表指针和偏移量,即就是将类B和类C继承改为虚拟继承:
class B: virtual public A
{}
class C : virtual public A
{}
对其进行监视,能够得到d的内存布局如下:
从这我们能够明显的看到,菱形虚拟继承比菱形继承的d中多存在一个指针,增加一个指针能够指向偏移量。
c++支持单继承和多继承,如果稍不注意就会出现菱形继承的问题,所以在写代码时尽量使用单继承。java语言设计的比较好,它只支持单继承,这就避免程序员在写代码时出错。
本文出自 “无心的执着” 博客,转载请与作者联系!