我有一个类A和另一个从它继承的类,B。我重写了一个接受类型A的对象作为参数的函数,所以我必须接受一个A.但是,我后来只调用函数B有,所以我想返回false,如果传递的对象不是B类,则不继续。
找出传递给我的函数的对象的最佳方法是什么?
答案 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;
}
希望这很有用。