10 Stimmen

Explizite Instanziierung einer Musterklasse und dynamic_cast in einer gemeinsam genutzten Bibliothek

Ich stolperte in ein Problem heute, dass ich nicht scheinen zu lösen. Ich kompiliere eine gemeinsam genutzte Bibliothek, die eine Vorlagenklasse enthält ( Derived<T> , deren Basis ist Base ) und einige explizite Instanziierungen dieser Klasse. Ich möchte, dass der Bibliotheksbenutzer von dieser Vorlagenklasse ausgehen kann. Das Problem tritt auf, wenn ich versuche dynamic_cast die Instanz des Benutzers aus Base* a Derived<T>* .

Ich habe das Problem auf diese MWE eingegrenzt:

Die gemeinsame Bibliothek enthält die folgenden Dateien:

Base.h

#ifndef BASE_H_
#define BASE_H_

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

#endif /* BASE_H_ */

Abgeleitet.h

#ifndef DERIVED_H_
#define DERIVED_H_    
#include <Base.h>

template <typename T>
class Derived : public Base {
public:  
    Derived();
    virtual ~Derived();
};

#endif /* DERIVED_H_ */

Abgeleitet.cpp

#include <Derived.h>

template <typename T>
Derived<T>::Derived() :
    Base() {
}

template <typename T>
Derived<T>::~Derived() {
}

// explicit instantiations
template class Derived<float>;
template class Derived<double>;
template class Derived<long double>;

Helfer.h

#ifndef HELPER_H_
#define HELPER_H_

#include <Base.h>

class Helper {
public:
    Helper(Base* m);
    virtual ~Helper();

};

#endif /* HELPER_H_ */

Helper.cpp

#include <Helper.h>
#include <Base.h>
#include <Derived.h>

#include <iostream>

using namespace std;

Helper::Helper(Base* m) {

    cout << "after received " << m << endl;
    cout << "after fom: " <<  dynamic_cast< Derived<float>* >(m) << endl;
    cout << "after dom: " <<  dynamic_cast< Derived<double>* >(m) << endl;
    cout << "after ldom: " <<  dynamic_cast< Derived<long double>* >(m) << endl;
    cout << "===" << endl;
}

Helper::~Helper() {
}

Und ein einfacher Code, der die Bibliothek verwendet, könnte sein:

test.cpp

#include <Derived.h>
#include <Helper.h>

#include <iostream>

using namespace std;

class MyModel : public Derived<double> {
public:
    MyModel() : Derived<double>() {
    };

    virtual ~MyModel() {
    };        

};

int main(int argc, char *argv[]) {

    MyModel om1;
    cout << "created mymodel " << &om1 << endl;
    cout << "before fom: " <<  dynamic_cast< Derived<float>* >(&om1) << endl;
    cout << "before dom: " <<  dynamic_cast< Derived<double>* >(&om1) << endl;
    cout << "before ldom: " <<  dynamic_cast< Derived<long double>* >(&om1) << endl;
    cout << "===" << endl;
    Helper root(&om1);

    return 0;
}

Das Problem ist, dass, wenn ich eine gemeinsame Bibliothek erstellen und verknüpfen test.cpp gegen sie, die dynamic_cast scheitert. Hier ist ein Beispiel für die Ausgabe:

created mymodel 0x7fff5fbff3e0
before fom: 0
before dom: 0x7fff5fbff3e0
before ldom: 0
===
after received 0x7fff5fbff3e0
after fom: 0
after dom: 0  // <<< Here I expected it to succeed and return a non-null pointer
after ldom: 0
===

Wenn ich jedoch die gesamte Bibliothek und das Beispiel zusammen kompiliere, gelingt der Cast:

created mymodel 0x7fff5fbff3e0
before fom: 0
before dom: 0x7fff5fbff3e0
before ldom: 0
===
after received 0x7fff5fbff3e0
after fom: 0
after dom: 0x7fff5fbff3e0
after ldom: 0
===

Meine Frage ist: Warum ist die dynamic_cast scheitern?

Und, unter der Voraussetzung, dass ich eine Klassenstruktur wie im Beispiel beibehalten und weiterhin eine gemeinsam genutzte Bibliothek verwenden möchte: Wie kann ich erfolgreich die Derived<some type>* gegossen aus einer Base* ?

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