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*
?