如何确定 C++类有一个虚函数表吗?
今天早些时候,我的一位朋友向我发送了以下挑战:
给定以下代码,提出
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。
A friend of mine sent me the following challenge earlier today:
Given the following code, propose an implementation of
OBJECT_HAS_VTABLE
so the program printsAnObject 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));
}
I've came up with the following solution which I think is decent enough:
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>()
Is there a better solution to this problem?
Edit
The solution doesn't have to be generic across all compilers. It can work on gcc, g++, MSVC... Just specify for which compiler your solution is known to be valid. Mine is for MSVC 2010.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
标准方法是 使用
std::is_polymorphic
来自 C++11/C++03 TR1/Boost 以确定类(及其基类)是否包含任何虚拟成员。The standard method is to use
std::is_polymorphic
from C++11/C++03 TR1/Boost to determine if a class (and its bases) contain any virtual members.为了完整起见,这是我的朋友刚刚发给我的答案。从它的外观来看,它可能与 TR1 的做法类似(尽管我自己没有看过代码)。
For completeness sake, here's the answer my buddy just sent me. From the look of it, it's probably similar to how TR1 does it (though I haven't looked at the code myself).
您可以使用 C++ 的以下属性:
dynamic_cast
在编译时失败。此类故障可与 SFINAE 一起使用。dynamic_cast
是一个有效的转换,返回完整多态对象的地址。因此,在 C++11 中:
You can use the following properties of C++:
dynamic_cast
fails at compile time if the argument is not a polymorphic class. Such a failure can be used with SFINAE.dynamic_cast<void*>
is a valid cast that returns the address of the complete polymorpic object.Hence, in C++11: