2012-04-24 3 views
1

Если у меня есть что-то вродевиртуальное наследование

class Base1 {}; 

class Base2 {}; 

class Derived : public Base1, public Base2 {}; 

Тогда порядок вызова конструктора на создание объекта из Derived является

Base1 
Base2 

т.е. в порядке их появления в

class Derived : public Base1, public Base2 {}; 

Но Если я изменю его на класс Derived: public Base1, virtual public Base2 {}; Тогда Порядок вызова конструктора становится

Base2 
Base1 

Я не могу понять, почему это так?

Еще одно простое сомнение: Что может быть значением и целью наследования Base1 практически.

+2

11 месяцев, когда вы находитесь на SO, и вы все еще не можете правильно отформатировать свои сообщения ?! – BlackBear

+0

Некоторая помощь http://gotw.ca/gotw/080.htm – DumbCoder

+0

Я предполагаю, что у вас есть опечатка, потому что вы объявляете «Base1» и «Base2», но затем используйте «Base» и «Base1». – Cornstalks

ответ

4

Это только правила. Созданный наиболее производный класс инициализирует все виртуальные базовые классы в иерархии, прежде чем начинать инициализацию своих не виртуальных прямых баз.

Правила приходят от стандарта (ISO/IEC 14882: 2011), раздел 12.6.2 [class.base.init]/10.

Обоснована такого подхода будет то, что он гарантирует, что все базы классы инициализируются до их производных классов независимо от того, являются ли они виртуальными базами.

1

Что касается наследования практически. Он вступает в игру, когда у вас есть производный класс, такой как ниже

class A {}; 
class B : public virtual A {} ; 
class C : public virtual A {} ; 
class D : B, C { } // this class has only one instance of A! 

aka проблема с алмазом!

3

О порядке инициализации Чарльз уже ответил правильно: это правила, сначала виртуальные базы в порядке объявления, а затем не виртуальные базы в порядке объявления, а затем переменные-члены в порядке декларация.

В чем смысл виртуального наследования? Это означает, что ваш объект происходит от этой конкретной базы, но если в иерархии более одного подобъекта (базы полного типа) наследуются практически от одного и того же базового типа, будет присутствовать только один базовый подобъект. Вы можете прочитать ключевое слово virtual как Я хочу поделиться своим base с другими объектами в полном размере.

struct ubase {}; 
struct sbase {}; 
struct A : ubase, virtual sbase {}; // has a sbase subobject, but is willing to share.. 
struct B : ubase, virtual sbase {}; // ... but want to have my own ubase 
struct C : A, B {};     // only one sbase subobject, shared by A and B 
             // ... but two ubase subobjects, A::ubase and B::ubase 

В соответствии с вторым вопросом, когда вы хотите использовать виртуальное наследование? Всякий раз, когда в иерархии типов вы можете наследовать одну и ту же базу более одного раза, а в вашем дизайне все эти вхождения базового класса - это всего лишь одно. В общем, весьма необычно использовать виртуальное наследование, кроме как в некоторых частных случаях.

Смежные вопросы