我偶然發現了一個我無法解決的問題。我正在編譯一個共享庫,其中包含一個模板類(Derived<T>
,其基數爲Base
)以及該類的一些顯式實例。我希望圖書館用戶能夠從這個模板類擴展。當我嘗試dynamic_cast
用戶的實例從Base*
到Derived<T>*
時,問題就出現了。在共享庫中顯式實例化模板化類和dynamic_cast
我縮小了問題該MWE:
共享庫包含以下文件:
Base.h
#ifndef BASE_H_
#define BASE_H_
class Base {
public:
Base();
virtual ~Base();
};
#endif /* BASE_H_ */
Derived.h
#ifndef DERIVED_H_
#define DERIVED_H_
#include <Base.h>
template <typename T>
class Derived : public Base {
public:
Derived();
virtual ~Derived();
};
#endif /* DERIVED_H_ */
Derived.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>;
Helper.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() {
}
和使用該庫可以是一個簡單的代碼:
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;
}
的問題是,當我創建共享庫和鏈接test.cpp
反對,該dynamic_cast
失敗。下面是一個例子輸出:
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
===
但是,如果我編譯整個庫和實例一起,轉換成功:
created mymodel 0x7fff5fbff3e0
before fom: 0
before dom: 0x7fff5fbff3e0
before ldom: 0
===
after received 0x7fff5fbff3e0
after fom: 0
after dom: 0x7fff5fbff3e0
after ldom: 0
===
我的問題是:爲什麼是dynamic_cast
失敗?
而且,在我想保持類似結構的前提下,繼續使用共享庫:我如何才能成功獲得從Base*
轉換而來?
關於縮小範圍的建議...... 1)確保傳遞給你的編譯器的選項對於你的lib組件和你的程序組件是一樣的......它們會影響管理符號的形成。 2)使用'[nm](http://linux.about.com/library/cmd/blcmdl1_nm.htm)'工具從您的庫對象和程序對象中轉儲符號...您應該看到相同的你的庫組件(已定義)和你的測試代碼(未定義)的損壞符號 – Andrew 2011-05-24 15:04:16