我有一個指向多態類型的指針,p
。我也有一個type_info
在同一個層次結構中的某個類,ti
。C++:使用typeinfo測試類繼承
如果我只比較typeid(*p) == ti
,那麼我可以在運行時測試指針是否指向該類的直接實例。
是否有類似的方式來使用C++的RTTI來測試*p
是否繼承了該類的?
我有一個指向多態類型的指針,p
。我也有一個type_info
在同一個層次結構中的某個類,ti
。C++:使用typeinfo測試類繼承
如果我只比較typeid(*p) == ti
,那麼我可以在運行時測試指針是否指向該類的直接實例。
是否有類似的方式來使用C++的RTTI來測試*p
是否繼承了該類的?
單靠標準C++沒有辦法做到這一點。如果您使用的是具有Itanium C++ ABI 的實現,你可以儘管做到這一點,例如:
#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
#include <memory>
class base {
protected:
base() {
}
public:
static bool check(const std::type_info& p) {
// Find the real type_info for single inheritance non virtual
const __cxxabiv1::__si_class_type_info* test = dynamic_cast<const __cxxabiv1::__si_class_type_info*>(&p);
return test ? typeid(base) == *test->__base_type : false;
}
virtual ~base() {}
};
class der : public base {
};
class foo {};
int main() {
der d;
foo f;
std::cout << base::check(typeid(d)) << "\n";
std::cout << base::check(typeid(f)) << "\n";
}
下面這個工作,因爲該類型有一個單一的,非virtuallly繼承的基礎。你可以支持更多的案例,儘管謹慎和類似dynamic_casts
。
儘管在某些情況下這是可能的,但我認爲你正在解決錯誤的問題 - 基於std::map
的解決方案更具可移植性,避免依賴這樣的實現細節。
容易混淆的名字命名,這是一個令人驚訝的大編譯/建築列表,而不是隻是安騰
是的,您可以使用dynamic_cast<>
。如果您嘗試投射到Base*
,它會執行運行時檢查,以查看您的課程是否確實是從Base
(或直接是基地)衍生而來。如果失敗,dynamic_cast<>
返回nullptr
。例如:
struct Base {
virtual ~Base() {}
};
struct AnotherBase {
virtual ~Base() {}
};
struct Derived : Base {};
Base * basePtr = new Base();
Base * derivedPtr = new Derived();
AnotherBase * anotherBasePtr = new Base();
// is derivedPtr a pointer to a class derived from AnotherBase ?
AnotherBase* test2 = dynamic_cast<AnotherBase*>(derivedPtr); // test2 == nullptr
// is basePtr a pointer to a class derived from Derived ?
Derived * test3 = dynamic_cast<Derived*>(basePtr); // test3 == nullptr
側節點:
如果dynamic_cast<>
被用於轉換指針,它返回要麼nullptr
或轉換後的指針。
但當dynamic_cast<>
是用來轉換引用它拋出一個異常在失敗的情況下。
運行時檢查dynamic_cast<>
只適用於多態類型。如果您的Base不包含任何虛函數(=非多態),將不可能安全地將Base*
轉換爲Derived*
。
不幸的是'dynamic_cast <>'只有在我知道類在_compile time_時纔有效。我不知道:我所有的都是類的'type_info'。我實際上並不需要投射指針,只是確定指向的對象是否繼承自我擁有'type_info'的類。 – 2012-07-15 11:32:02
@DavidGiven我誤解了你的問題。所以不,你不能。但是你可以創建一個map
沒關係,謝謝。我已經有了一個自定義RTTI的計劃來做到這一點,但想要檢查我是否真的需要它。 – 2012-07-15 12:05:27
十分感謝柔印。我一直在研究C++ ABI。工作一小時後,我有了這個演示:http://pastebin.com/j7DYY5ej。在某些情況下,這是一個檢查繼承的代碼。我爲這些類型實現了運算符==,!=,<,>,< =,>> =。我打算改進這種類型方程式並將其用於我的項目中。 請注意,我在Linux下使用了G ++ 4.8。
我不,唉。 (我甚至沒有STL)。我認爲這將是答案,但無法找到任何明確的說法。哦,那麼,自定義RTTI,那麼... – 2012-07-15 12:04:24
@DavidGiven - 這可能是你的實現有一個類似的ABI。 – Flexo 2012-07-15 12:06:30