我想知道现代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一样。
答案 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
支持。
将enum
或int
字段添加到为每个派生类进行不同初始化的基础也可以。
另一种选择是创建模板函数,并存储指向它的指针,如下所示:
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_convertible和std::is_same。
答案 4 :(得分:-1)
instanceof
或dynamic_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 ++标记它们。