dynamic_cast 没有转换的类型检查功能?

dynamic_cast type checking functionality without the cast?

关于这个主题有很多问题,但 none 似乎专门解决了这个问题:给定一个不允许用虚函数解决所有问题的代码库(就像你通常做的那样)有一个功能:

/** Check if obj is a T, including base classes. */
template <class T>
inline bool is_a(const basic &obj)
{
    return dynamic_cast<const T *>(&obj) != 0;
}

但很明显,即使没有必要,演员表也会被制作出来。如何编写此函数以仅检查,即使用 dynamic_cast 功能而不进行实际转换?假设用虚函数代替对该函数的调用是不切实际的,或者为此目的实现一个穷人的 RTTI。

编辑:在标题中添加了问号,强调了对可能性的怀疑

没有等效的功能。你只有两个选择。

  1. 开始手动滚动 RTTI(最差的选择),包括访客。
  2. 继续使用dynamic_cast。

我不知道您为什么甚至关心防止指针调整,因为这是几个 vtable 查找(到已经在缓存中的 vtable 中)并执行几个减法的相当微不足道的情况。 dynamic_cast 的所有实际工作都将在这两种情况下完成。此外,如果不将指针强制转换为该类型,我看不出 is_a 的结果有什么用处。

没有简单的方法来做你想做的事,主要是因为它没有真正意义,因此没有人决定提供它。

如果基础 class 不是多态的,

dynamic_cast() 也会失败,这意味着它没有任何虚拟方法。这意味着 B 可能继承自 A,但是 B* 到 A* 上的 dynamic_cast() 将失败,因为 A 没有任何虚函数 .

幸运的是,我们有 C++11:std::is_base_of<>http://en.cppreference.com/w/cpp/types/is_base_of

即使 A 和 B 不是多态的,它也能工作,而且它在编译时也能工作,这意味着没有 运行 时间开销

示例:

class A {};
class B : public A{};

int main (){
B b;
if (std::is_base_of<A,decltype(b)>::value){
   std::cout<<"b can be up-cast to A*";
}
return 0;
}

(可以查看:http://coliru.stacked-crooked.com/a/a5612738047ff3a5

确保事先使用 std::remove_pointerstd::remove_reference 删除任何引用或指针,如果要处理它们

请注意,实际转换只是向指针添加一个偏移量。确定偏移量所需的任何步骤也需要确定转换是否可能。一个好的优化器无论如何都会优化最后的添加,因为将一个常量添加到一个非空指针,除了空测试之外不使用它没有任何效果。

因此,任何不改进设计的替代品都不会产生可衡量的效果;因此,如果由于某种原因无法实现更好的设计,正确的替代方法是保持功能不变。