6 Stimmen

dynamic_cast schlägt fehl

Ich habe eine Basisklasse und eine abgeleitete Klasse. Jede Klasse hat eine .h-Datei und eine .cpp-Datei.

Ich tue dynamic_cast der Basisklasse Objekt an die abgeleitete Klasse im folgenden Code:

h-Dateien:

class Base
{
  public:
    Base();
    virtual ~Base();
};

class Derived : public Base
{
  public:
    Derived(){};
    void foo();
};

class Another
{
  public:
    Another(){};
    void bar(Base* pointerToBaseObject);
};

cpp-Dateien:

Base::Base()
{
    //do something....
}
Base::~Base()
{
    //do something....
}
void Derived::foo()
{
    Another a;
    a.bar(this);
}
void Another::bar(Base* pointerToBaseObject)
{
    dynamic_cast<Derived*>(pointerToBaseObject)
}

Aus irgendeinem seltsamen Grund schlägt das Casting fehl (gibt NULL zurück). Das Casting ist jedoch erfolgreich, wenn ich die Implementierung des Konstruktors der Klasse Derived von der Datei .h in die Datei .cpp verschiebe.

Was kann sie verursachen?

Der Compiler ist gcc 3.1, auf Linux-SUSE. BTW, ich sehe dieses Verhalten nur auf dieser Plattform, und der gleiche Code funktioniert gut in Visual Studio.

8voto

Haben Sie eine virtuelle Funktion in Base? Sonst wird es nicht funktionieren. Wenn nichts anderes, machen Sie seinen dtor virtuell.

Ich weiß nicht, ob die Frage schon von dem anderen gestellt wurde, der seine Antwort gelöscht hat, aber ich glaube, es war etwas anderes: Machst du den dynamic_cast vom Konstruktor der Basen aus? Wenn ja, wird das nicht funktionieren. Der Compiler wird denken, dass die Base der am meisten abgeleitete Typ ist, ähnlich wie wenn Sie eine virtuelle Funktion aufrufen und es endet mit dem Aufruf der Version der Base.

6voto

Pieter Punkte 16973

Der Code, wie gepostet, sollte nicht scheitern, vorausgesetzt, Sie haben eine virtuelle Funktion in der Basisklasse (wie litb darauf hingewiesen).

Aber ich glaube, jeder aktuelle Compiler generiert eine "Base class is not polymorphic" Art von Fehler, wenn Sie nicht hatten, so dass wahrscheinlich nicht das Problem sein wird.

Das einzige, was ich mir vorstellen kann, ist, dass aufgrund eines seltsamen Fehlers alles inlined wird und keine vtable generiert wird. Aber wenn Sie den Konstruktor in der C++-Datei setzen, entscheidet der Compiler, nicht alles zu inlinen und löst die Erstellung einer vtable aus, so dass Ihr Cast funktioniert.

Aber das ist eine sehr wilde Vermutung, und ich glaube nicht, dass irgendein Compiler einen solchen Fehler enthält (?)

Wenn Sie eine eindeutige Antwort wünschen, stellen Sie mehr Code ein. Und den verwendeten Compiler / Plattform.

EDIT: Ich sehe den aktualisierten Code

Ich denke, Sie sollten zumindest Derived von Base ableiten ;) (Ich nehme an, das ist ein Tippfehler)

Aber nachdem ich den Code gesehen habe, ist das Einzige, was mir einfällt, dass gcc (fälschlicherweise) alles inlines und keine vtable für Derived generiert. Für was es wert ist, läuft dies gut mit gcc 4.0 kompiliert

3.1 ist mittlerweile über 7 Jahre alt... wenn es eine Möglichkeit gibt, aufzurüsten, würde ich es tun.

4voto

Mr Fooz Punkte 102791

Machen Sie den Destruktor virtuell, und platzieren Sie ihn (oder zumindest eine virtuelle Methode) in der .cpp-Datei.

Einige Compiler (z.B. gcc) suchen nach dem ersten Nicht-Inline-Körper einer virtuellen Methode und verwenden diesen, um zu entscheiden, wo die Tabelle der virtuellen Methoden abgelegt werden soll. Wenn Sie keine virtuellen Methoden mit Body in einer .cpp-Datei haben, wird die virtuelle Methodentabelle nicht erstellt.

Sie müssen mindestens eine virtuelle Methode haben, damit dynamic_cast funktioniert. Dynamic_cast verwendet die Tabelle, um Typinformationen herauszufinden, und wenn es keine virtuellen Methoden gibt, wird keine Tabelle erstellt.

Wenn Sie eine Klasse haben, von der Sie erwarten, dass sie unterklassifiziert wird, und die einen Destruktor hat, oder wenn die Klasse Instanzvariablen hat, die Klassen mit Destruktoren sind, dann sollten Sie Ihren Destruktor unbedingt virtuell machen (auch wenn er einen leeren Körper hat). Andernfalls wird die von Ihnen erwartete Bereinigung für Instanzen von Unterklassen nicht stattfinden.

0voto

Sean Punkte 58522

Tun Sie dies in Visual C++? Ich glaube, Sie verwenden, um Laufzeit-Typ-Informationen (RTTI) in der Compiler-Einstellung zu aktivieren, damit dies funktioniert.

Bitte schimpfen Sie nicht mit mir, wenn ich das falsch verstanden habe. Es ist eine Weile her, dass ich C++ benutzt habe!!!

0voto

plinth Punkte 46829

Wenn ich mir Ihren Code ansehe, kann ich keine Vererbung erkennen. Haben Sie das vergessen? Abgeleitet ist nicht von etwas abgeleitet.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X