2016-05-25 17 views
0

Betrachten Sie die folgende abstrakte Klasse AbstractEngine:C++: Aufruf statische Methode von statischer Methode geerbt

class AbstractEngine { 
    static void init(); 
    static std::string getName(); 
}; 

und die folgenden 2 Implementierer Klassen berücksichtigen:

class Engine1 : public AbstractEngine { 
    static std::string getName(); 
}; 

class Engine2 : public AbstractEngine { 
    static std::string getName(); 
}; 

Und die init() Funktion die richtigen nennen sollte getName() nach der Art der Klasse:

void AbstractEngine::init() { 
    std::cout << getName() << std::endl; 
} 

Zum Beispiel, wenn ich Engine1::init() nennen, möchte ich es Engine1::getName() nennen und nicht AbstractEngine::getName()

Wie kann ich AbstractEngine::init() wirklich machen die korrekte Umsetzung der getName() zu nennen?

+1

keine Möglichkeit, eine tatsächliche Instanz einer Klasse ohne. –

+3

"nach dem Typ der Instanz" ... Aber welche Instanz, wenn Ihre Funktion statisch ist? – Quentin

+0

Ich meine, wenn ich 'Engine1 :: init()', möchte ich es nennen 'Engine1 :: getName()' – SomethingSomething

Antwort

10

Sie die CRTP verwenden können, das heißt AbstractEngine eine Template-Klasse machen, dann, wenn Sie erben, erben von AbstractEngine<EngineN>:

template <typename T> 
class AbstractEngine { 
public: 
    static void init() { 
     std::cout << T::getName() << std::endl; 
    } 
}; 

class Engine1 : public AbstractEngine<Engine1> { 
public: 
    static std::string getName() { return "Engine1"; } 
}; 

class Engine2 : public AbstractEngine<Engine2> { 
public: 
    static std::string getName() { return "Engine2"; } 
}; 

Live Demo


Wenn Sie auch einige dynamische polymorphe Verhalten benötigen, Sie können eine gemeinsame Nicht-Template-Basisklasse erstellen:

class AbstractEngine { 
    //I assume you would have some virtual functions here 
}; 

template <typename T> 
class AbstractEngineImpl : public AbstractEngine { 
public: 
    static void init() { 
     std::cout << T::getName() << std::endl; 
    } 
}; 

class Engine1 : public AbstractEngineImpl<Engine1> { 
public: 
    static std::string getName() { return "Engine1"; } 
}; 

class Engine2 : public AbstractEngineImpl<Engine2> { 
public: 
    static std::string getName() { return "Engine2"; } 
}; 
1

Die Methode getName() sollte nicht statisch sein. Weder die init() Methode.

2

Sie versuchen, polymorphes Verhalten zu erhalten, aber mit statischen Funktionen. Dies ergibt keinen Sinn. Definitionsgemäß ist polymorphes Verhalten einer bestimmten Instanz von Objekten zugeordnet - statischen Funktionen ist jedoch keine Instanz zugeordnet.

Wenn Sie polymorphe Verhalten wollen (wie Sie Tag schon sagt), sollten Sie diese Redesign:

class AbstractEngine { 
    virtual void init(); 
    virtual std::string getName(); 
}; 

class Engine1 : public AbstractEngine { 
    std::string getName() override; 
}; 

class Engine2 : public AbstractEngine { 
    std::string getName() override; 
}; 
+3

Nun, das war eine C++ Frage – Smeeheey

+1

Auch [siehe diese] (http://stackoverflow.com/questions/8095457/why-do-we-say-dass-eine-statische-Methode-in-Java-ist-nicht-eine-virtuelle-Methode) in Bezug auf die Java-Kommentar – Smeeheey

+2

Ich stimme nicht mit Ihrer Definition von Polymorphismus . Es gibt einen Unterschied zwischen statischem Polymorphismus (verfügbar in C++ mit Templates und dem CRTP) und dynamischem Polymorphismus (virtuelle Funktionen, RTTI). – TartanLlama

Verwandte Themen