Ваши ошибки обычно происходят из-за того, что CMyClass
не имеет конструктора по умолчанию (потому что вместо этого вы определяете CMyClass(int)
), поэтому необходимо явно создать экземпляр ваших родителей с помощью конструктора CMyClass(int)
, который вы иметь. Так, например, в вашем определении CMyClass
вам нужно добавить вызов к CMyClass(int)
в списке инициализатора
CMyClass(int x) : AddOn1<CBase>(x), CMyClass<AddOn2, AddOn3>(x) //send x down
Теперь, когда мы CMyClass
отправляем x
по линии, вашей специализации базового случая (CMyClass<empty, empty, empty>
) необходимо иметь конструктор, который принимает x
, но ничего не делает с ним
template<>
class CMyClass<empty, empty, empty> {
public:
CMyClass(int) {} //do nothing
};
Теперь компилятор может найти нужные конструкторы и создать ваши классы, как вы ожидаете
Просто чтобы объяснить, почему строки типа CMyClass<AddOn_A> A(100)
работают, это потому, что A
(в этом примере) имеет только одного родителя, CMyClass<empty, empty, empty>
, и вашу специализацию
template<> class CMyClass< empty, empty, empty > {};
имеет конструктор по умолчанию, потому что он пустой (или, более формально, потому что он не определяет других конструкторов). Это сразу ломается, когда вы вызываете CMyClass<AddOn_A, AddOn_B> AB(100)
, потому что у него есть два родителя, CMyClass<AddOn_B, empty, empty>
и CMyClass<empty, empty, empty>
, однако первый не имеет конструктора по умолчанию, поэтому компилятор не знает, как его построить , Вот почему мы должны добавить эту строку в список инициализаторов, поэтому мы сообщаем компилятору создать CMyClass<AddOn_B, empty, empty>
с помощью его конструктора CMyClass(int x)
(обратите внимание, что это означает, что компилятор также попытается создать CMyClass<empty, empty, empty>
с параметром x
, поэтому нам нужно добавить конструктор к той специализации, который будет принимать параметр).