2016-06-09 6 views
0

ich den folgenden Linkfehler mit dem folgenden Code erhalten:Wie gegen eine überlastetes Template-Methode verknüpfen

undefined reference to Ibase :: Name() const'`

Hinweis in der Basisklasse, ist es die virtuelle Aufruf Funktionsname(). Die Implementierung der Klasse Name der abgeleiteten Klasse soll aufgerufen werden, der Linker sucht jedoch nach IBase :: Name, nicht nach Derived :: Name(). Wie löst man das?

template<class T_Extendable> 
class IBase 
{ 
public: 
    virtual ~IBase() = default; 
    virtual const std::string& Name() const = 0; 
}; 

template<class T_Extendable> 
class Base : public IBase<T_Extendable> 
{ 
public: 
    virtual ~Base() { "Destructing " << Name(); } // use virtual function Name() 
}; 

class Derived : public Base<Foo> 
{ 
public: 
    virtual ~Derived() = default; 
    const std::string& Name() const final { return "Derived"; } // implement pure virtual method IBase::Name() 
}; 
+0

'const std :: Zeichenfolge & Name() const final {return" Derived "; } 'ist ein Rezept für eine Katastrophe. Ihr Compiler sollte Sie warnen, dass Sie einen Verweis auf ein temporäres Objekt zurückgeben, und sehen Sie nach, was das bedeutet. – Praetorian

+0

Liebe Liebe stackoverflow! Natürlich sieht das nicht nach unserem Produktionscode aus, sondern wurde destilliert, um das Problem zu kommunizieren. Ich denke, Smeehey hat etwas dagegen. – rkemp

Antwort

3

Sie rufen eine virtuelle Funktion vom Destruktor auf. Nach den Regeln für die Objektlebensdauer des Standards bedeutet dies, dass selbst dann, wenn das zerstörte Objekt eine Derived ist, der Destruktor Base nicht mehr auf die virtuellen Funktionsüberschreibungen des meist abgeleiteten Typs (in diesem Fall Derived) zugreifen kann . Daher versucht es, die in IBase deklarierte Version aufzurufen, die nicht definiert ist, so dass Sie einen Linker-Fehler erhalten.

Hinweis: Dies ist der entsprechende Abschnitt des Standards, die dieses Verhalten [class.cdtor] gibt:

4 Member-Funktionen, einschließlich virtueller Funktionen (10.3), können während des Baus oder Zerstörung aufgerufen werden (12.6.2). Wenn eine virtuelle Funktion direkt oder indirekt von einem Konstruktor oder von einem Destruktor aufgerufen wird, einschließlich während der Konstruktion oder der Zerstörung der nicht statischen Datenelemente der Klasse , und das Objekt, auf das der Aufruf zutrifft, ist das Objekt (nennen Sie es x) im Bau oder bei der Zerstörung, Die aufgerufene Funktion ist der letzte Overrider in der Klasse des Konstruktors oder des Destruktors und nicht in einer Klasse überschrieben.

+0

Super! Danke Smeeheey, das war auch dummes Glück, weil unsere Basisklasse mehrere virtuelle Methoden hat, die Name() aus Zweckmäßigkeit aufrufen, wählte ich den Destruktor, um die Verwendung zu demonstrieren, die wir tatsächlich im Code in einem Protokoll machen Botschaft. Wir verbin- den gute Kenntnisse, wenn wir den Aufruf auskommentieren, was natürlich sinnvoll ist, das abgeleitete wurde zerstört, wenn die Basisklasse aufgerufen wird. – rkemp

Verwandte Themen