在钻石继承体系中,一定要用虚继承!
1.下面的代码块儿无法通过编译,原因是,A3无法确定自己到底是用哪一个父类中的函数。
class A { public: virtual void f(){} virtual void g(){} }; class A1 : virtual public A { public: virtual void f() { } }; class A2: virtual public A { public: virtual void f() { } }; class A3 : public A1, public A2 { };
下面这个通过了编译。原因是,A3确定了自己的实现方式。
class A { public: virtual void f(){} virtual void g(){} }; class A1 : virtual public A { public: virtual void f() { } }; class A2: virtual public A { public: virtual void f() { } }; class A3 : public A1, public A2 { public: virtual void f() { } };下面的代码中,A3仍然无法确定自己的实现方式。但是可以定义A3的对象。这是因为每一个函数只有一个虚函数表。
class A { public: virtual void f(){} virtual void g(){} }; class A1: public A{}; class A2: public A{}; class A3: public A1, public A2{};同理,下面的代码也能通过编译:
class A { public: virtual void f(){} virtual void g(){} }; class A1: public A //不需要虚继承 { public: virtual void f(){} }; class A2: public A //不需要虚继承 { public: virtual void g(){} }; class A3: public A1, public A2 { };同理,下面的代码也能通过编译:
class A { public:virtual void f(){} }; class A1: public A{}; class A2: public A{}; class A3: public A1, public A2{};
但是。这三种方式存在一个致命的弱点,就是,如果不用虚继承。下面的代码无法通过编译:
A3 a3; A& a = a3;用虚继承:则可通过
class A { public: virtual void f(){} virtual void g(){} }; class A1: virtual public A { public: virtual void f(){} }; class A2: virtual public A { public: virtual void g(){} }; class A3: public A1, public A2 { }; A3 a3; A& a = a3; 虚继承的含义是,不一定会为孙子类提供实现。 为孙子类提供实现的有可能是自己,也有可能是兄弟,也有可能是父类。 在钻石继承体系中,一定要用虚继承来避免在钻石体系中的二义性
