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


我有一个A类和另一个继承它的类,B。我重写了一个接受A类对象作为参数的函数,所以我必须接受一个A.但是,我后来调用只有B的函数,所以我想返回false,如果传递的对象不是B类,则不继续。

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


120
2017-12-09 05:06


起源




答案:


dynamic_cast应该可以解决问题

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

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

如果您尝试转换为指向不是实际对象类型的类型的指针,则转换的结果将为NULL。如果您尝试强制转换为引用不是实际对象类型的类型,则强制转换将抛出一个 bad_cast 例外。

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


136
2017-12-09 05:14



你是什​​么意思,在Base类中必须有一个虚函数才能使dynamic_cast工作。在我看来这很重要,我只会猜测。 - GiCo
OK发现它:运行时类型信息(RTTI)仅适用于多态的类,这意味着它们至少有一个虚方法。 dynamic_cast和typeid需要RTTI。 - GiCo
不 dynamic_cast 如果它不可兑换扔?有没有办法在不产生投掷的情况下做到这一点? - jww
A* aptr = dynamic_cast<A*>(ptr); //不应该是这样的 - Mehdi Karamosly


动态演员是最适合您的问题描述, 但我只想补充一点,你可以找到类类型:

#include <typeinfo>

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

118
2017-12-01 14:04



好的,如果你真的不知道你的对象是什么。接受的答案假定你这样做。 - unludo
是类型信息标准? - xus
@xus是的。它是标准头文件的一部分 - Amey Jah
一世 别看 怎么样。类型ID名称不需要有用,并且是实现定义的。 - Shoe
最有趣的是:同一个类的实例名称不必相等。但是,typeid本身必须比较相同类的实例,请参阅 stackoverflow.com/questions/1986418/typeid-versus-typeof-in-c - FourtyTwo


这被称为RTTI,但你几乎肯定想在这里重新考虑你的设计,因为找到类型并根据它做特殊的事情会使你的代码变得更脆弱。


20
2017-12-09 05:09



真正。不幸的是,我正在研究一个现有项目,所以我不能真正改变设计,或A类中的任何东西。 - lemnisca


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

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


8
2017-12-09 05:13





你在找吗? dynamic_cast<B*>(pointer)


6
2017-12-09 05:09





为了完成,我将建立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

4
2018-03-31 18:53



很好的例子。谢谢! - user


正如其他人所说,你可以使用dynamic_cast。但通常使用dynamic_cast来查找您正在处理的派生类的类型表明设计不好。如果要覆盖一个将A的指针作为参数的函数,那么它应该能够使用类A本身的方法/数据,而不应该依赖于类B的数据。在你的情况下,如果你不是覆盖确保您编写的方法仅适用于B类,那么您应该在B类中编写一个新方法。


2
2017-12-09 06:51