2008-12-09 203 views
115

我有一个类A和从它继承另一个类的类型,B.我重写接受类型A的对象作为参数的函数,因此我必须接受的A.不过,我稍后调用只有B有的函数,所以如果传递的对象不是B类,我想返回false而不继续。查找C中的对象++

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

回答

134

的dynamic_cast应该做的伎俩

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

dynamic_cast关键词从一个指针或引用类型到另投下了一个基准,执行运行时检查,以确保投的有效性。

如果试图转换为指针类型,它是不是一个类型的实际对象的,演员的结果将是NULL。如果您尝试转换为引用不是实际对象类型的类型,则该转换将抛出异常。

确保有在基类中的至少一个虚拟功能进行dynamic_cast的工作。

+0

你的意思是在基类中必须有一个虚函数才能使dynamic_cast工作。我认为这很重要,我只是猜测。 – GiCo 2015-08-19 08:20:37

+0

确定发现它:运行时类型信息(RTTI)仅适用于多态的类,这意味着它们至少有一个虚拟方法。 dynamic_cast和typeid需要RTTI。 – GiCo 2015-08-19 08:54:23

+0

如果它不可转换,不会抛出`dynamic_cast`?有没有办法做到这一点,而不产生投掷? – jww 2016-08-31 11:38:26

19

这就是所谓的RTTI,但你几乎肯定要重新考虑你的设计在这里,因为找到的类型,做基于它特别的东西使你的代码更脆。

+3

确实。不幸的是,我正在研究一个现有的项目,所以我无法真正改变设计,或者A类中的任何东西。 – lemnisca 2008-12-09 05:23:38

6

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

2

你的描述有点混乱。

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

+1

应该注意,如果您执行的参考演员失败,您将得到一个异常*。 即dynamic_cast (t)。 失败的指针转换返回NULL。 (t) – AlfaZulu 2008-12-09 05:14:21

+0

是的,我应该澄清,更好。谢谢。 我希望有一个词的C型描述是通过引用,而不是按价值。 – Uri 2008-12-09 05:21:11

8

可能嵌入到您的对象的ID的“标签”,并用它的类A的对象和类B.

的对象之间进行区分然而,这显示了在设计的一个缺陷。理想情况下,A中没有的B中的方法应该是A的一部分,但保留为空,B将覆盖它们。这消除了特定于类的代码,更符合OOP的精神。

2

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

0

使用重载函数。不需要的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 
    } 
}; 
113

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

#include <typeinfo> 

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

因为你的类不是多态的。试试:

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

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

3

只要是完整的,我将建立蓄客Robocide的,并指出不使用名称()的typeid可以单独使用:

#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 
0

如果您可以访问增强库,也许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; 
} 

希望这是有用的。