在运行时确定对象类型的最佳方法
Best way to determine the type of an object at runtime
所以我想做的是实现消息模式。据我了解,用户将根据我输入的消息类型采取行动,而不是执行操作的消息类型。因此,这就是我的处理方式:
我想获取对象的数据类型,以便执行 switch 语句,但我不太确定从哪里开始。
我查看了 google 并做了一些研究,但 none 是成功的。这是我试过的:
- Decltype:与我想要的还差得远
- typeof : 不太清楚怎么用
- 动态转换:与我想要的不相近
基本上,我最后想要的是这样的:
switch (typeof(a)) {
class_a : //do something
class_b : //do something
}
if 语句对我来说同样有效。谁能帮我吗?我更喜欢使用标准库。
标准 C++ 中没有 typeof
(尽管有一个 GCC 扩展名)。您正在寻找包含对象的 运行 时间类型信息 (RTTI) 的 typeid
operator. This returns a reference to a static const
std::type_info
实例。您可以将结果与您感兴趣的各种 类 的 typeid
进行比较。
举个简单的例子 (see it run at ideone):
#include <iostream>
#include <typeinfo>
class A {
public:
virtual ~A() {}
};
class B: public A {};
class C: public A {};
int main() {
const A& a = C{};
const auto& id = typeid(a);
if(id == typeid(B)) {
std::cout << "Got a B." << std::endl;
}
else if(id == typeid(C)) {
std::cout << "It's a C!" << std::endl;
}
return 0;
}
(请注意,您不能使用 switch
,因为对象不是整数。)此示例将打印 It's a C!
.
请注意,一般来说,使用 RTTI 不应该是您的第一反应(如果您来自 Java 等语言,请特别注意,在这些语言中,动态类型及其相关的速度受到影响 -被认为是理所当然的)。
RTTI 与其他面向对象的范例相比相对较慢,甚至是动态调度(virtual
函数)。如果您正在尝试实现消息模式,请考虑将显式值作为消息传递,而不是将您的其他对象硬塞进该模式并招致昂贵的 RTTI 开销。
dynamic-cast : not close to what I want
你抱错了。动态演员当然可以做你想做的事。
if (dynamic_cast<c1*>(a)) { ... }
else if (dynamic_cast<c2*>(a)) { ... }
*a
的静态类型必须是多态的。同样的事情适用于参考。如果您按值传递它,它不会也不能工作。
然而,这是一种危险且容易出错的实现方式。如果您想为 M 种接收者类型实现 N 种消息类型,并且所有 M×N 种操作都可能不同,请考虑使用访问者模式,尤其是它的非循环实现。
所以我想做的是实现消息模式。据我了解,用户将根据我输入的消息类型采取行动,而不是执行操作的消息类型。因此,这就是我的处理方式:
我想获取对象的数据类型,以便执行 switch 语句,但我不太确定从哪里开始。
我查看了 google 并做了一些研究,但 none 是成功的。这是我试过的:
- Decltype:与我想要的还差得远
- typeof : 不太清楚怎么用
- 动态转换:与我想要的不相近
基本上,我最后想要的是这样的:
switch (typeof(a)) {
class_a : //do something
class_b : //do something
}
if 语句对我来说同样有效。谁能帮我吗?我更喜欢使用标准库。
标准 C++ 中没有 typeof
(尽管有一个 GCC 扩展名)。您正在寻找包含对象的 运行 时间类型信息 (RTTI) 的 typeid
operator. This returns a reference to a static const
std::type_info
实例。您可以将结果与您感兴趣的各种 类 的 typeid
进行比较。
举个简单的例子 (see it run at ideone):
#include <iostream>
#include <typeinfo>
class A {
public:
virtual ~A() {}
};
class B: public A {};
class C: public A {};
int main() {
const A& a = C{};
const auto& id = typeid(a);
if(id == typeid(B)) {
std::cout << "Got a B." << std::endl;
}
else if(id == typeid(C)) {
std::cout << "It's a C!" << std::endl;
}
return 0;
}
(请注意,您不能使用 switch
,因为对象不是整数。)此示例将打印 It's a C!
.
请注意,一般来说,使用 RTTI 不应该是您的第一反应(如果您来自 Java 等语言,请特别注意,在这些语言中,动态类型及其相关的速度受到影响 -被认为是理所当然的)。
RTTI 与其他面向对象的范例相比相对较慢,甚至是动态调度(virtual
函数)。如果您正在尝试实现消息模式,请考虑将显式值作为消息传递,而不是将您的其他对象硬塞进该模式并招致昂贵的 RTTI 开销。
dynamic-cast : not close to what I want
你抱错了。动态演员当然可以做你想做的事。
if (dynamic_cast<c1*>(a)) { ... }
else if (dynamic_cast<c2*>(a)) { ... }
*a
的静态类型必须是多态的。同样的事情适用于参考。如果您按值传递它,它不会也不能工作。
然而,这是一种危险且容易出错的实现方式。如果您想为 M 种接收者类型实现 N 种消息类型,并且所有 M×N 种操作都可能不同,请考虑使用访问者模式,尤其是它的非循环实现。