[英]How to determine if a C++ class has a vtable?
我的一個朋友今天早些時候給我發送了以下挑戰:
給定以下代碼,提出
OBJECT_HAS_VTABLE
的實現,以便程序打印AnObject has a vtable = 0, AnObjectWithVTable has a vtable = 1
。
class AnObject
{
int m_a;
void DoSomething() {}
public:
AnObject() {m_a = 0;}
};
class AnObjectWithVTable
{
int m_b;
virtual void DoStuff() { }
public:
AnObjectWithVTable() {m_b = 0;}
};
void main()
{
printf("AnObject has a vtable = %i, AnObjectWithVTable has a vtable = %i\n",
OBJECT_HAS_VTABLE(AnObject),
OBJECT_HAS_VTABLE(AnObjectWithVTable));
}
我想出了以下我認為足夠體面的解決方案:
template <typename T>
bool objectHasVtable()
{
class __derived : public T {};
T t;
__derived d;
void *vptrT=*((void **)&t);
void *vptrDerived=*((void **)&d);
return vptrT != vptrDerived;
}
#define OBJECT_HAS_VTABLE(T) objectHasVtable<T>()
這個問題有更好的解決方案嗎?
編輯
該解決方案不必在所有編譯器中通用。 它可以在 gcc、g++、MSVC 上工作……只需指定您的解決方案對哪個編譯器有效。 我的是 MSVC 2010。
標准方法是使用C++11/C++03 TR1/ Boost 中的std::is_polymorphic
來確定類(及其基類)是否包含任何虛擬成員。
#include <type_traits>
#define OBJECT_HAS_VTABLE(T) (std::is_polymorphic<T>::value)
為了完整起見,這是我的好友剛剛發給我的答案。 從它的外觀來看,它可能類似於 TR1 的做法(雖然我自己沒有看過代碼)。
template<class T>
class HasVTable
{
public :
class Derived : public T
{
virtual void _force_the_vtable(){}
};
enum { Value = (sizeof(T) == sizeof(Derived)) };
};
#define OBJECT_HAS_VTABLE(type) HasVTable<type>::Value
您可以使用 C++ 的以下屬性:
dynamic_cast
在編譯時失敗。 這種故障可以與 SFINAE 一起使用。dynamic_cast<void*>
是一個有效的強制轉換,它返回完整的多態對象的地址。因此,在 C++11 中:
#include <iostream>
#include <type_traits>
template<class T>
auto is_polymorphic2_test(T* p) -> decltype(dynamic_cast<void*>(p), std::true_type{});
template<class T>
auto is_polymorphic2_test(...) -> std::false_type;
template<class T>
using is_polymorphic2 = decltype(is_polymorphic2_test<T>(static_cast<T*>(0)));
struct A {};
struct B { virtual ~B(); };
int main() {
std::cout << is_polymorphic2<A>::value << '\n'; // Outputs 0.
std::cout << is_polymorphic2<B>::value << '\n'; // Outputs 1.
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.