关于虚继承(在钻石继承体系中,一定要用虚继承!)

xiaoxiao2021-02-28  87

在钻石继承体系中,一定要用虚继承!

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; 虚继承的含义是,不一定会为孙子类提供实现。 为孙子类提供实现的有可能是自己,也有可能是兄弟,也有可能是父类。 在钻石继承体系中,一定要用虚继承来避免在钻石体系中的二义性

 

转载请注明原文地址: https://www.6miu.com/read-74371.html

最新回复(0)