2014-06-22 3 views
1
class A { 
public: 
    A(int) { 
     cout << "Base class" << endl; 
    } 
}; 

class B : virtual public A { 
public: 
    virtual void do_something() = 0; 
}; 

class C : public B { 
public: 
    C() 
     : A(1) { 
     cout << "C class" << endl; 
    } 

    virtual void do_something() { 
    } 
}; 

Ошибка компилятора: когда объект для C создаются, компилятор результирующая ошибка какнесколько наследования уровня выполнения конструктора

error: no matching function for call to ‘A::A()’

почему компилятор ожидает конструктор класса А по умолчанию?

+0

Благодарим лорда за clang-format. – chris

+0

Прочтите раздел FAQ ISOCPP по этим концепциям http://isocpp.org/wiki/faq/proper-inheritance & http://isocpp.org/wiki/faq/basics-of-inheritance –

+0

[Какой компилятор?] (Http : //coliru.stacked-crooked.com/a/c0d980808c205ea9) – chris

ответ

1

Поскольку нет явной инициализации для B части C в C::C(), компилятор использует конструктор по умолчанию B, чтобы сделать это.

C() 
    : A(1) { 
    cout << "C class" << endl; 
} 

эквивалентно:

C() 
    : B(), A(1) { 
    cout << "C class" << endl; 
} 

по умолчанию конструктор B пытается инициализировать A часть с помощью конструктора по умолчанию A, который не существует. Это сообщение об ошибке компилятора.

Вы можете исправить это одним из следующих способов:

  1. Обеспечить конструктор по умолчанию для A.
  2. Предоставить конструктор по умолчанию для B, в котором используется значение A(int) для инициализации части B.

Update

Почему компилятор хочет хотеть A::A() в B::B()? Поскольку он не знает, что во время выполнения будет создан экземпляр C.

Рассмотрим следующий сценарий:

#include <iostream> 
using namespace std; 

class A 
{ 
    public: 
     A(int) 
     { 
     cout << "Came to A(int)" << endl; 
     } 
}; 

class B : virtual public A 
{ 
    public: 
     virtual void do_something(){}; 
}; 

int main() 
{ 
    B b; 
} 

Это понятно, почему B::B() нужно вызвать A::A(int) или ожидать A::A(). Поскольку компилятор не может, apriori, выяснить, является ли B самым производным классом, он должен убедиться, что есть способ инициализировать A от B, если это необходимо.

+0

Самый производный класс отвечает за инициализацию подобъекта 'A', поскольку он наследуется практически. – chris

+0

Найдено цитату (§10.1 [class.mi]/4): * Для каждого отдельного базового класса, который является указанным виртуальным, наиболее производный объект должен содержать подобъект одного базового класса этого типа * – chris

+0

@chris, я согласен с Что Вы говорите. Это все еще оставляет вопрос: как инициализируется 'B'? Вот где код OP получает ошибку компилятора. –

0

B не имеет конструктора по умолчанию.

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

Даже если B конструктор по умолчанию не должен вызывать конструктор A когда B используется в качестве базового класса, вы по-прежнему нужен действующий конструктор по умолчанию для B, если вы хотите использовать его.

0

Вот разбивка этой проблемы, в C++ 11:

  • Поскольку нет пользователя объявлено конструктора для B, конструктор без параметров неявно объявлен как по умолчанию. Однако, поскольку для A нет конструктора по умолчанию, этот конструктор определяется как удаленный. Ref [class.ctor]#5. (Это на самом деле означает, что B никогда не может быть создан, потому что у него нет не удаленных конструкторов).

  • C «s конструктор не упоминает B в списке инициализатора, поэтому B субобъект по умолчанию инициализируется. Ref [class.base.init]#8

  • Инициализация по умолчанию объекта без доступного конструктора по умолчанию означает, что программа плохо сформирована. Ref [dcl.init]#6

Существует оговорка в [class.base.init]#8, что базовый класс не требуется конструктор , если это виртуальный базовый класс абстрактного класса. Однако это не так. A - такой класс, но B нет.

Основная информация - не существует допустимого конструктора для подобъекта BC.

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