8

I want to know what the modern C++11 equivalent of Java's instanceof. I have seen this SO post but it is quite old and was wondering if there's a more modern, better solution in C++11?

I was hoping there's a possibility of using a switch construct without having to resort to a manual enum class.

class A {

};

class B : public A {

}

class C : public A {

}

on_event(A& obj)
{
    switch (obj) {
       case A:
       case B:
       case C:
    }
}

My base class does not have any virtual methods or functions. I am representing an expression tree for a parser and the base class is just a polymorphic holder - like an ADT in Haskell/OCaml.

4

5 回答 5

12

同样的答案仍然适用,并且在 C++ 中一直是这样的:

if (C * p = dynamic_cast<C *>(&obj))
{
    // The type of obj is or is derived from C
}
else
{
    // obj is not a C
}

这种构造需要A是多态的,即具有虚拟成员函数。

另请注意,此行为与 compare 不同typeid(obj) == typeid(C),因为后者测试确切的类型标识,而动态转换以及 Javainstanceof仅测试目标类型是最派生对象类型的基类。

于 2014-10-12T12:54:58.650 回答
0

在 C++ 中,普通旧数据 (POD) 没有运行时类型信息。所描述的类都只占用 1 个字节,并且在任何具有空基类优化的编译器中都具有相同的运行时表示。

因此,您想要的无法完成。

向基类添加虚拟析构函数会增加 RTTI 和dynamic_cast支持。

enumorint字段添加到每个派生类以不同方式初始化的基类也可以。

另一种选择是创建一个模板函数,并存储一个指向它的指针,如下所示:

using my_type_id=void(*)();
template<class>void get_my_type_id_helper(){};
template<class T> my_type_id get_my_type_id(){return get_my_type_id_helper<T>;}

然后将 a 存储my_type_idA适当的初始化中。这是对 RTTI 的重新发明,当您需要更多功能时,您将接近 C++ RTTI 开销。

在 C++ 中,您只需为所要求的内容付费:您可以要求没有 RTTI 的课程,您已经这样做了,并得到了它。

RTTI 是运行时类型信息。POD 是普通的旧数据,一个 C++03 术语。许多类不是 POD:简单的方法是添加virtual析构函数。C++11 具有更细粒度的标准布局和聚合术语。

从技术上讲,RTTI 和 POD 并不是相互对立的:有些没有 RTTI 的类不是 POD。

请注意,MSVC 具有不生成 RTTI 的选项,并且其激进的 Comdat 折叠可能会破坏我在上面所做的手动 RTTI,这两种情况都违反了标准。

于 2014-10-12T22:34:29.040 回答
0

也许您对我在您提到的旧 SO 帖子中发布的答案感兴趣。

https://stackoverflow.com/a/49296405/1266588

答案提出了一个instanceof不使用dynamic_cast基于 C++11、模板元编程RTTI的实现。一个小型性能测量应用程序表明它比dynamic_cast使用编译器优化更有效。

于 2018-03-15T10:05:59.677 回答
-1

如果您愿意将自己限制在编译时已知的类型(而不是通过 vtables 类实例上的指针工作) - 那么 C++11 及更高版本确实有一个instanceof等价物:它是std::is_base_of

您可能还想查看std::is_convertiblestd::is_same

于 2014-10-12T13:26:32.973 回答
-1

不要那样做。在大多数情况下,当您要求使用instanceof或时,您应该检查您的设计dynamic_cast

为什么?您很可能违反了 Liskov 的替代原则

这种方法怎么样:

class A {
   public:
     virtual void action();
     virtual ~A();
};

class B : public A {
   public: void action() override;
};

class C : public A {
   public: void action() override;
};

void on_event(A& obj)
{
   obj.action();
}

请注意,正如@Yakk 指出的那样,无论如何您至少需要一种virtual方法来获得动态多态性。并且有一条规则说:当你至少有一个虚方法时,总是还要在基类中写一个虚析构函数。

您可以使用模板和专业化或类型标记来完成所有这些工作,但我从您的问题中得到——来自 Java——您还不想去那里。你真的很喜欢虚拟方法,不是吗?抱歉,您必须用 C++ 标记它们。

于 2017-03-28T19:56:24.470 回答