在 C + + 中查找对象的类型

我有一个类 A 和另一个从它继承的类 B。我正在覆盖一个接受类型 A 的对象作为参数的函数,所以我必须接受一个类型 A。然而,我后来调用了只有类型 B 才有的函数,所以我想返回 false,如果传递的对象不是类型 B,就不继续。

找出传递给函数的对象类型的最佳方法是什么?

372007 次浏览

这就是所谓的 RTTI,但是您几乎肯定要重新考虑这里的设计,因为找到类型并基于它做一些特殊的事情会使您的代码更加脆弱。

你在找 dynamic_cast<B*>(pointer)

你的描述有点混乱。

一般来说,尽管一些 C + + 实现具有相应的机制,但是您不应该询问类型。相反,应该对指向 A 的指针执行 Dynamic _ cast。这将在运行时检查指向 A 的指针的实际内容。如果你有一个 B,你会得到指向 B 的指针,否则,你会得到一个异常或者 null。

可能会在对象中嵌入一个 ID“标记”,并使用它来区分类 A 的对象和类 B 的对象。

然而,这显示了设计中的一个缺陷。理想情况下,B 中 A 没有的那些方法,应该是 A 的一部分,但留空,并且 B 覆盖它们。这消除了特定于类的代码,更符合 OOP 的精神。

Dynamic _ cast 应该可以做到这一点

TYPE& dynamic_cast<TYPE&> (object);
TYPE* dynamic_cast<TYPE*> (object);

dynamic_cast关键字将数据从一个指针或引用类型强制转换到另一个,执行运行时检查以确保强制转换的有效性。

如果试图转换为指向非实际对象类型的指针,则转换的结果将为 NULL。如果试图强制转换以引用非实际对象类型的类型,则强制转换将引发 bad_cast异常。

确保 Base 类中至少有一个虚函数可以使 Dynamic _ cast 工作。

维基百科主题 执行期型态讯息

RTTI 只适用于多态类,这意味着 他们至少有一个虚拟的方法。实际上,这不是一个 限制,因为基类必须有一个虚析构函数来 允许派生类的对象执行适当的清理 从基指针中删除。

正如其他人指出的那样,您可以使用 Dynamic _ cast。但通常使用 Dynamic _ cast 查找正在处理的派生类的类型表明设计不好。如果你重写一个以 A 的指针作为参数的函数,那么它应该能够处理 A 类本身的方法/数据,而不应该依赖于 B 类的数据。在您的情况下,如果您确信您正在编写的方法只能用于类 B,那么您应该在类 B 中编写一个新的方法,而不是重写。

使用重载函数。不需要 Dynamic _ cast 甚至 RTTI 支持:

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


class Foo {
public:
void Bar(A& a) {
// do something
}
void Bar(B& b) {
Bar(static_cast<A&>(b));
// do B specific stuff
}
};

动态强制转换是描述问题的最佳方式, 但我想补充的是,你可以通过以下方式找到类类型:

#include <typeinfo>


...
string s = typeid(YourClass).name()

因为您的类不是多态的。请尝试:

struct BaseClas { int base; virtual ~BaseClas(){} };
class Derived1 : public BaseClas { int derived1; };

现在 BaseClas是多态的。我将 class 改为 struct,因为 struct 的成员在默认情况下是公共的。

为了完整起见,我将在 Robocide 的基础上进行构建,并指出可以单独使用 typeid而不使用 name () :

#include <typeinfo>
#include <iostream>


using namespace std;


class A {
public:
virtual ~A() = default; // We're not polymorphic unless we
// have a virtual function.
};
class B : public A { } ;
class C : public A { } ;


int
main(int argc, char* argv[])
{
B b;
A& a = b;


cout << "a is B: " << boolalpha << (typeid(a) == typeid(B)) << endl;
cout << "a is C: " << boolalpha << (typeid(a) == typeid(C)) << endl;
cout << "b is B: " << boolalpha << (typeid(b) == typeid(B)) << endl;
cout << "b is A: " << boolalpha << (typeid(b) == typeid(A)) << endl;
cout << "b is C: " << boolalpha << (typeid(b) == typeid(C)) << endl;
}

产出:

a is B: true
a is C: false
b is B: true
b is A: false
b is C: false

如果你能访问提升库,也许 < em > type _ id _ with _ cvr () 函数就是你所需要的,它可以 提供数据类型,但不要删除 < strong > < em > const、 volatile 和 & & & 修饰符 。下面是 C + + 11中的一个简单例子:

#include <iostream>
#include <boost/type_index.hpp>


int a;
int& ff()
{
return a;
}


int main() {
ff() = 10;
using boost::typeindex::type_id_with_cvr;
std::cout << type_id_with_cvr<int&>().pretty_name() << std::endl;
std::cout << type_id_with_cvr<decltype(ff())>().pretty_name() << std::endl;
std::cout << typeid(ff()).name() << std::endl;
}

希望这个有用。