2014-01-20 4 views
3

Смотрите следующий код:Почему абстрактные производные классы должны инициализировать виртуальный базовый класс?

struct Object; 

struct Component 
{ 
    Component(Object* obj) { } 
}; 

struct Renderable : public virtual Component 
{ 
    virtual void Render() = 0; 
}; 

struct AnimationRenderer : public Renderable 
{ 
    AnimationRenderer(Object* obj) : Component(obj) { } 
    virtual void Render() { } 
}; 

Это не может скомпилировать, потому что нет соответствующего вызова Component::Component() из Renderable::Renderable().

я могу сделать эту работу образца, давая Renderable конструктор, такие как Renderable() : Component(NULL) { }, даже если визуализируемый никогда не смогут инициализировать компонент.

Потому что Renderable - абстрактный класс, он никогда не может быть создан непосредственно. Поскольку он фактически наследуется от Component, он никогда не сможет вызвать инициализацию Component.

В чем причина языка, требующего кода, который никогда/никогда не будет вызван?

+0

Я также открыт для предложений по лучшему названию. –

+0

Я думаю, что это то, что «абстрактное» означает - то, о чем мы можем думать, но не как конкретный объект. – Dinesh

+0

абстрактный класс может быть создан, компилятором. – yngccc

ответ

2

На самом деле язык не требует этого. Ваш компилятор не использует текущие правила C++.

12.6.2p8 говорит (полужирная шахта для выразительности):

[Примечание: абстрактный класс никогда не является наиболее производным классом, таким образом, его конструкторы не инициализировать виртуальные классы базы, поэтому соответствующего мем- инициализаторы могут быть опущены. - конец примечание]

Я не могу найти это правило в C++ 03, так что это признанный недостаток в C++, который с тех пор было зафиксировано. Найдите обновление компилятора, поддерживающее C++ 11.

Ближайшее родственное правило в C++ 03 можно найти в разделе был 12.6.2p6:

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

+0

gcc, clang и cl all требуют инициализатора. Это новое? –

+0

Спасибо за обновление! Что объясняет его! –

+0

@dauphic: Извините за оригинальную ложную тревогу. Я знал, что самый производный класс будет строить виртуальные базы перед не виртуальными прямыми базами, но я предполагал, что он будет смотреть на непосредственно наследующий класс для аргументов конструктора. Можете ли вы сказать, что я избегаю виртуального наследования? –

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