2016-06-02 11 views
5

Given następujący przykład:Mieszanie dziedziczone konstruktor z klasy bazowej z niestandardowym construcutor

struct tag1 { }; 
struct tag2 { }; 

template<typename T> 
class Base { 
public: 
    Base(T /*value*/) { } 
    Base(tag1) { } 
}; 

template<> 
class Base<void> { 
public: 
    Base() { } 
    Base(tag1) { } 
}; 

template<typename T = void> 
class MyClass : public Base<T> { 
public: 
    using Base<T>::Base; 

    MyClass(tag2) : Base<T>(tag1{}) { } 
}; 

int main() { 
    { 
    MyClass<> defaultConstructible; 
    MyClass<> tagConstructible(tag2{}); 
    } 
    { 
    MyClass<int> valueConstructible(0); 
    MyClass<int> tagConstructible(tag2{}); 
    } 
} 

Klasa MyClass mogą być programowane z wszelkich typów, powinien być domyślny constructible gdy typ T równa void, inaczej jest konstruktywny z typu T, jak napisano w funkcji main.

Używam klasy bazowej zależnej od parametru, aby uzyskać to zachowanie (poprzez użycie konstruktora klasy bazowej).

Potrzebuję również dodać konstruktory do hierarchii klas, które akceptują inne parametry, jak widać w źródłowym przykładzie (znaczniki structs).

Czy można to zrobić bez deklarowania wszystkich konstruktorów w tej samej klasie? Ponieważ zmieszanie konstruktorów nadklasy z niestandardowymi te dadzą się następujący komunikat o błędzie:

main.cpp: In function 'int main()': 
main.cpp:30:15: error: no matching function for call to 'MyClass<>::MyClass()' 
    MyClass<> defaultConstructible; 
       ^~~~~~~~~~~~~~~~~~~~ 
main.cpp:22:18: note: candidate: MyClass<>::MyClass(tag1) 
    using Base<T>::Base; 
        ^~~~ 
main.cpp:22:18: note: candidate expects 1 argument, 0 provided 
main.cpp:25:3: note: candidate: MyClass<T>::MyClass(tag2) [with T = void] 
    MyClass(tag2) : Base<T>(tag1{}) { } 
    ^~~~~~~ 
main.cpp:25:3: note: candidate expects 1 argument, 0 provided 
main.cpp:20:7: note: candidate: constexpr MyClass<>::MyClass(const MyClass<>&) 
class MyClass : public Base<T> { 
     ^~~~~~~ 
main.cpp:20:7: note: candidate expects 1 argument, 0 provided 
main.cpp:20:7: note: candidate: constexpr MyClass<>::MyClass(MyClass<>&&) 
main.cpp:20:7: note: candidate expects 1 argument, 0 provided 

Demo

+1

Jak tylko wprowadzisz sparametryzowany konstruktor dla 'MyClass', żaden domyślny konstruktor nie zostanie wygenerowany przez kompilator, więc czego właściwie się spodziewasz? –

+0

Dobra rada, spodziewam się, że klasa 'MyClass' będzie domyślnie konstruktywna, gdy parametr' T' jest nieważny, ponieważ używam go z klasy bazowej (która jest jawnie tam zadeklarowana). –

+0

_ "Oczekuję, że klasa MyClass będzie domyślna, gdy parametr T jest nieważny, ponieważ używam go z klasy bazowej" _ To zachowanie dedukcji nie jest _ "dziedziczone" _. –

Odpowiedz

2

Po wprowadzić własny konstruktor domyślny konstruktor nie będzie się niejawnie zdefiniowane - nie ważne, że próbujesz to odziedziczyć.

Można po prostu wyraźnie zdefiniowania domyślnego konstruktora jako domyślnie:

template<typename T = void> 
class MyClass : public Base<T> { 
public: 
    using Base<T>::Base; 

    MyClass() = default; 
    MyClass(tag2) : Base<T>(tag1{}) { } 
}; 

Tutaj MyClass<> staje się domyślnym constructible, ale nadal nie jest MyClass<int> ponieważ Base<int> nie jest.

0

przekształcania z mojego 1 komentarz:

Jak wkrótce wprowadzi sparametryzowanego konstruktora dla MojaKlasa ma domyślnego konstruktora zostanie wygenerowany przez kompilator

można łatwo rozwiązać ten problem zapewniając domyślnego konstruktora od MyClass jawnie:

template<typename T = void> 
class MyClass : public Base<T> { 
public: 
    using Base<T>::Base; 

    MyClass() = default; // <<<<<<<<<<< 
    MyClass(tag2) : Base<T>(tag1{}) { } 
}; 

Demo

Domyślne zachowanie Base<T> nie jest dziedziczone, ale domyślny konstruktor jest wywoływany za pomocą implementacji = default;.

Powiązane problemy