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

时间:2008-12-09 05:06:52

标签: c++ types

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

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

11 个答案:

答案 0 :(得分:141)

dynamic_cast应该做的伎俩

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

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

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

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

答案 1 :(得分:133)

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

#include <typeinfo>

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

答案 2 :(得分:23)

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

答案 3 :(得分:9)

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

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

答案 4 :(得分:7)

您正在寻找dynamic_cast<B*>(pointer)

答案 5 :(得分:7)

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

答案 6 :(得分:3)

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

答案 7 :(得分:3)

因为你的班级不是多态的。尝试:

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

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

答案 8 :(得分:2)

您的描述有点令人困惑。

一般来说,尽管某些C ++实现具有相应的机制,但您不应该询问类型。相反,你应该在指向A的指针上做一个dynamic_cast。这将是在运行时,将检查指向A的指针的实际内容。如果你有一个B,你将获得指向B的指针。否则,你将得到一个例外或null。

答案 9 :(得分:1)

使用重载功能。不需要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
    }
};

答案 10 :(得分:1)

如果您可以访问boost库,可能需要 type_id_with_cvr() 功能,provide data type without removing const, volatile, & and && modifiers。这是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;
}

希望这很有用。