什么是C ++ 11相当于Java的实例

时间:2014-10-12 12:52:39

标签: java c++ c++11 instanceof multiple-languages

我想知道现代C ++ 11相当于Java的实例。我已经看到了这个SO post,但它已经很老了,并且想知道在C ++ 11中是否有更现代,更好的解决方案?

我希望有可能使用switch结构,而不必使用手动枚举类。

class A {

};

class B : public A {

}

class C : public A {

}

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

我的基类没有任何虚拟方法或函数。我代表一个解析器的表达式树,基类只是一个多态持有者 - 就像Haskell / OCaml中的ADT一样。

5 个答案:

答案 0 :(得分: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具有多态性,即具有虚拟成员函数。

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

答案 1 :(得分:0)

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

因此你无法做到。

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

enumint字段添加到为每个派生类进行不同初始化的基础也​​可以。

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

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>;}

然后将my_type_id存储在适当初始化的A中。这是重新发明RTTI,并且随着您需要更多功能,您将接近C ++ RTTI开销。

在C ++中,你只需支付你所要求的费用:你可以申请没有RTTI的课程,你可以参加。

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

技术上,RTTI和POD并不是彼此相反的:没有RTTI的类不是POD。

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

答案 2 :(得分:0)

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

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

答案提供instanceof的实现,不使用dynamic_cast基于C ++ 11,模板元编程 RTTI 。如果使用编译器优化,小型性能测量应用程序会证明它比dynamic_cast更有效。

答案 3 :(得分:-1)

如果您愿意将自己限制在编译时已知的类型(而不是通过使用vtable的类实例上的指针) - 那么C ++ 11及更高版本确实具有instanceof等效类型:这是std::is_base_of

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

答案 4 :(得分:-1)

不要这样做。在大多数情况下,当您要求instanceofdynamic_cast时,您应该检查您的设计。

为什么呢?您很可能违反了Liskov's substitiontin principle

这种方法怎么样:

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 ++标记它们。