3.10 C++虚基类 虚继承
参考:http://www.weixueyuan.net/view/6367.html
总结:
本例即为典型的菱形继承结构,类A中的成员变量及成员函数继承到类D中均会产生两份,这样的命名冲突非常的棘手,通过域解析操作符已经无法分清具体的变量了。为此,C++提供了虚继承这一方式解决命名冲突问题。虚继承只需要在继承属性前加上virtual关键字。
在多继承时很容易产生命名冲突问题,如果我们很小心地将所有类中的成员变量及成员函数都命名为不同的名字时,命名冲突依然有可能发生,比如非常经典的菱形继承层次。类A派生出类B和类C,类D继承自类B和类C,这个时候类A中的成员变量和成员函数继承到类D中变成了两份,一份来自A派生B然后派生D这一路,另一份来自A派生C然后派生D这一条路。
例1:
class A { public: void setx(int a){x = a;} int getx(){return x;} private: int x; }; class B: public A { public: void sety(int a){y = a;} int gety(){return y;} private: int y; }; class C: public A { public: void setz(int a){z = a;} int getz(){return z;} private: int z; }; class D: public B, public C { //...... };
本例即为典型的菱形继承结构,类A中的成员变量及成员函数继承到类D中均会产生两份,这样的命名冲突非常的棘手,通过域解析操作符已经无法分清具体的变量了。为此,C++提供了虚继承这一方式解决命名冲突问题。虚继承只需要在继承属性前加上virtual关键字。
例2:
#include <iostream> using namespace std; class A { public: void setx(int a){x = a;} int getx(){return x;} private: int x; }; class B: virtual public A { public: void sety(int a){y = a;} int gety(){return y;} private: int y; }; class C: virtual public A { public: void setz(int a){z = a;} int getz(){return z;} private: int z; }; class D: public B, public C { //...... }; int main() { D test; test.setx(10); cout<<test.getx()<<endl; return 0; }
在本例中,类B和类C都是继承类A都是虚继承,如此操作之后,类D只会得到一份来自类A的数据。在本例的主函数中,定义了类D的对象test,然后通过该对象调用从类A间接继承来的setx和getx成员函数,因为B和C继承自类A采用的是虚继承,故通过D调用setx和getx不会有命名冲突问题,因为D类只得到了一份A的数据。