2016-09-09 3 views
4
class MyDerived: public Incredble<Difficult< And<Complicated, Long>>, And<Even, Longer>, BaseClass, Name> 
{ 
public: 
    MyDerived(); 
} 


MyDerived::MyDerived 
: ???(params) 
{} 

Gibt es eine Möglichkeit, einen Basiskonstruktor aufzurufen, ohne seinen vollständigen Namen zu schreiben und ohne typedefing?Call-Base-Klassenkonstruktor ohne Benennung der Klasse

Der Grund ist eindeutig, Code-Duplizierung zu vermeiden und mehrere Positionen zu ändern, wenn sich ein Detail in den Basisklassen-Template-Parametern ändert.

Stufe 2 dafür:

template <uint32 C> 
class MyDerived: public Incredble<Difficult< And<Complicated, Long>>, And<Even, Longer>, BaseClass, Name> 
{ 
public: 
    MyDerived(); 
} 

template <uint32 C> 
MyDerived::MyDerived<C> 
: ???(C) 
{ 
} 
+1

Was mit 'using' oder' typedef' falsch? – max66

+1

es verschmutzt den umschließenden Namespace –

+0

abhängig von Ihrem Konstruktor können Sie 'using' und Konstruktor Delegation (die Namespace nicht verschmutzt) verwenden. Hängt davon ab, wenn Sie Probleme mit Parametern oder Vorlagen haben. – Hayt

Antwort

7

könnten Sie injected-class-name verwenden. Incredible<...>::Incredible bezieht sich auf sich selbst, und da MyDerived kein Klassenvorlage ist, unqualifizierte Lookup im Rahmen ihrer Basisklassen aussehen:

MyDerived::MyDerived 
: Incredble(params) 
{} 

Wenn Incredible ist ein abhängig Namen, dann müssen Sie es qualifizieren. Sie können einfach tatsächlich verwenden, um die abgeleiteten Typnamen der Basisklasse injiziert-class-name (h/t Johannes Schaub-litb) zu qualifizieren:

MyDerived::MyDerived 
: MyDerived::Incredible(params) 
{} 

Dies funktioniert in allen Fällen.

+1

ändert sich das, wenn MyDerived ein Classe-tempate ist? weil es für mich aber der Template-Parameter ist. Ich kann das zur Anfangsfrage hinzufügen –

+0

Detail Namespaces sind immer schön. – Hayt

+0

@vlad_tepesch Die Antwort adressiert diesen Fall bereits - Sie können den injected-class-name nicht verwenden, aber Sie können immer eine Alias- oder Alias-Vorlage in einem nichtöffentlichen Namespace hinzufügen – Barry

0

Wenn Sie nicht using oder typedef zu verwenden pflegt „Verschmutzung des umschließenden Namensraum“ zu vermeiden, können Sie using in der Klasse/Struktur verwenden.

Ein Beispiel

#include <map> 

template <typename ...> 
class foo 
{}; 

struct A : public foo<int, std::tuple<long, char, std::map<std::string, int>>> 
{ 
    using base_t = foo<int, std::tuple<long, char, std::map<std::string, int>>>; 

    A() : base_t{} 
    { }; 
}; 

int main() 
{ } 
+1

Sie haben den Klassennamen "Incredble" zwei Mal benutzt. – Liviu

+0

@Liviu - das ist richtig; aber Sie können 'base_t' für andere Zwecke in derselben Klasse verwenden (andere Konstruktoren, zum Beispiel); Um die Duplizierung zu vermeiden, können Sie 'base_t' außerhalb der Struktur definieren, aber Sie verunreinigen den externen Namespace – max66

+0

, der von STL-Objekt abgeleitet wird, ist im Allgemeinen keine gute Idee. Ich meine, die Idee ist in Ordnung, aber das Beispiel ist schlecht – Hayt