C ++ - virtuelle Funktion undefiniert zur Verbindungszeit - warum?

7

Ich habe ein paar Probleme mit virtuellen Funktionen in C ++, und ich könnte sie in einem Konstruktor missbrauchen. Das Problem ist, dass beim Verknüpfen einer von mir geschriebenen Komponente lib in meine endgültige ausführbare Datei eine virtuelle Funktion als undefiniert markiert wird, obwohl ich dafür eine Implementierung geschrieben und verlinkt habe.

Ich habe die folgende Klasse:

%Vor%

In meiner Unterklasse:

%Vor%

Und die Unterklassen-Quelldatei:

%Vor%

Wie Sie sehen können, rufe ich eine virtuelle Funktion in meinem Konstruktor auf. Soweit ich das beurteilen kann, sollte das in Ordnung sein, da mir bewusst ist, dass mein Unterklassenkonstruktor nicht aufgerufen wurde, sodass ich keine Instanzvariablen verwenden kann, sondern einfach ein paar unterklassenspezifische Elemente zu a hinzufüge Std :: Karte.

%Vor%

Was mache ich hier falsch? Bitte fragen Sie, wenn Sie mehr Informationen benötigen, wollte es so kurz wie möglich halten!

    
Max 12.02.2011, 20:23
quelle

3 Antworten

18

Sie rufen die virtuelle Funktion vom Basisklassenkonstruktor auf. Es gibt spezielle Regeln für den Versand von virtuellen Funktionen während des Baus und der Zerstörung:

Wenn der Konstruktor der Basisklasse UdpConnection ausgeführt wird, ist der dynamische Typ des Objekts effektiv UdpConnection , nicht UdpClient . Der letzte Overrider der ausgewählten virtuellen Funktion ist also der für UdpConnection , nicht die abgeleitete Klasse, UdpClient .

Das heißt, wenn Sie initSysHandlers() im Konstruktor UdpConnection aufrufen, wird immer UdpConnection::initSysHandlers() aufgerufen, nicht die Überschreibung in der am weitesten abgeleiteten Klasse. Da Sie keine Definition von UdpConnection::initSysHandlers() angegeben haben, erhalten Sie den Linker-Fehler.

Der Rat des Experten ist, dass Sie "Virtuelle Funktionen während der Konstruktion oder der Zerstörung niemals aufrufen" sollten .

>     
James McNellis 12.02.2011, 20:28
quelle
2

Rufen Sie virtuelle Funktionen zur Konstruktionszeit nicht auf. Die Konstruktion geht von der Basisklasse zur abgeleiteten Klasse. Daher weiß der Konstruktor UdpConnection::UdpConnection noch nicht, dass die Klasse geerbt wurde. Die vtable für die abgeleitete Klasse wurde zu diesem Zeitpunkt noch nicht gebildet, und die Adresse der überladenen Funktion, die aufgerufen werden soll, ist nicht bekannt.

    
ak. 12.02.2011 20:26
quelle
0

Sie sollten niemals virtuelle Funktionen in einem Konstruktor oder Destruktor aufrufen, da sie nicht das erwartete Verhalten haben. Das Objekt wurde nicht vollständig erstellt, bis der Konstruktor zurückkehrt.

Der Basisklassenkonstruktor wird vor dem Konstruktor der abgeleiteten Klasse aufgerufen. Daher werden die Datenelemente und Funktionen der Basisklasse zuerst erstellt und definiert. In diesem Fall versucht der UdpConnection-Ctor, UdpConnection :: initSysHandlers, NOT UdpClient :: initSysHandlers aufzurufen, da er noch nicht erstellt wurde. Da UdpConnection :: initSysHandlers rein virtuell ist, ist es zu diesem Zeitpunkt nicht definiert.

    
cchampion 12.02.2011 20:27
quelle