2015-02-27 3 views
10

Рассмотрим приведенный ниже код. И g ++, и clang ++ жалуются (правильно), что конструктор A(int) является приватным в классе D. Обратите внимание, что поскольку A является виртуальным базовым классом D, A должен быть инициализирован в mem-initializer класса D, который является самым производным классом, согласно §12.6.2/7 в C++ 11. См. live example.Неявно вызов конструктора недоступного виртуального базового класса

class A { 
public: 
    A(int i) : x(i) { } 
    A() : x(1) {} 
    int x; 
}; 

class B : private virtual A { 
protected: 
    B(int i) : A(i) { } }; 

class C : public B, private virtual A { 
protected: 
    C(int i) : A(i), B(i) { } 
}; 

class D : public C { 
public: 
    D() : A(1), C(3) { } 
}; 

int main() { 
    D d; 
} 

Но оба компиляторы не заморачиваться с тем, что конструктор по умолчанию для класса A также является частным в D, то есть, как компилировать и выполнять код, как правило, если мы определим конструктор для D следующим образом:

D() : C(3) {} 

И это неправильно, насколько я могу судить.

Обратите внимание, что оба компилятора не компилировать (правильно), если мы определим:

D() : A(), C(3) {} 
+0

Возможно, вы захотите добавить живой пример, который показывает случай, когда вы озадачены, например, 'D(): C (3) {}' –

+0

@RSahu Даже для случая 'D(): C (3) {}' указал выше ? Я спрашиваю об этом, потому что я действительно не знаю разницы между компилятором, который я использовал в Coliru (стандартный std = C++ 11) и 4.7.3, который вы упомянули выше – Belloc

+0

@RSahu С 'D(): C (3) ', я не получаю ошибки в GCC 4.7.4. Какие параметры командной строки вы используете с 4.7.3, чтобы получить ошибку? – hvd

ответ

9

But both compilers don't bother with the fact that the default constructor for class A is also private in D ,

Нет, конструктор по умолчанию не является частным. Базовый класс A является закрытым, но его конструктор по умолчанию является общедоступным.

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

Когда базовые классы неявно построены, эти базовые классы не называются. Они просто инициализируются по умолчанию (на 12.6.2p8), а инициализация по умолчанию просто проверяет, доступен ли конструктор (на 8.5p7).

Вы можете сказать, что проблема с именем базового класса, не используя частное унаследованного имени базового класса, но с использованием глобально доступное именем ::A:

D() : ::A(1), C(3) { } 

Live example

+0

Конструктор по умолчанию доступен только в том случае, если он не предоставляется пользователем. – Belloc

+0

@Belloc Это не имеет смысла. Пожалуйста, перечитайте свой комментарий, подумайте о том, что вы хотите сказать, а затем перефразируйте его. – hvd

+0

§12.1/5 (C++ 11) 'Неявно объявленный конструктор по умолчанию является встроенным публичным членом своего класса. ' – Belloc

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