如果对象是ClassA类型或派生类型ClassB,我如何在运行时检查?在一种情况下,我必须单独处理两个实例
ClassA* SomeClass::doSomething ( ClassA* )
{
if( /* parameter is of type base class */) {
} else if { /* derived class */ ) {
}
}
也许我可以说派生类ClassB具有一些特殊功能。但是,如何在不更改现有类ClassA的情况下执行此操作?
答案 0 :(得分:22)
打开这样的确切类型通常是一个非常糟糕的主意。通过这样做,您将方法与ClassA
的派生类紧密耦合。你应该使用多态。在A类中引入virtual
方法,在B类中重写它,然后在方法中调用它。
即使我因某种原因被迫处理外部函数本身的功能,我也会这样做:
class ClassA {
public: virtual bool hasSpecificFunctionality() { return false; }
};
class ClassB : public ClassA {
public: virtual bool hasSpecificFunctionality() { return true; }
};
ClassA* SomeClass::doSomething ( ClassA* arg )
{
if (arg->hasSpecificFunctionality()) {
} else {
}
}
答案 1 :(得分:15)
使用dynamic_cast
,如下所示:
ClassA* SomeClass::doSomething(ClassA* a)
{
if (dynamic_cast<DerivedClass*>(a)) {
...
} else if (dynamic_cast<BaseClass*>(a)) {
...
}
}
如果dynamic_cast<T *>(ptr)
不是0
类型的指针, ptr
将返回T
,否则将返回T
类型的指针。
dynamic_cast
,这是设计/代码设计不良的指标。如果可以避免,请尝试这样做,因为在最终的可执行文件中需要RTTI。
答案 2 :(得分:4)
为什么不在ClassB上使用doSomething()方法来处理ClassB的额外功能?这是多态性的本质。
答案 3 :(得分:3)
语法是:
ClassA* SomeClass::doSomething ( ClassA* pa )
{
ClassB* pb = dynamic_cast<ClassB*>(pa);
if( pb ) ...
(请注意,这只适用于多态类层次结构。也就是说,必须涉及虚函数。)
但是,你应该尽量避免这种情况。你需要什么才能通过应用虚函数来解决?
答案 4 :(得分:3)
其他人指出,开启类型通常是一个坏主意,所以我不会。如果你真的必须这样做,你可以使用typeid
运算符来打开对象的动态类型:
ClassA* SomeClass::doSomething ( ClassA* a )
{
if (typeid(*a) == typeid(ClassA)) {
/* parameter is of type base class */
} else if (typeid(*a) == typeid(ClassB)) {
/* a specific derived class */
} else {
/* some other derived class */
}
}
dynamic_cast
类似,但测试可兑换性,而不是相等性:
ClassA* SomeClass::doSomething ( ClassA* a )
{
if (ClassB *b = dynamic_cast<classB*>(a)) {
/* parameter is, or is derived from, ClassB */
} else {
/* parameter is, or is derived from, ClassA but not ClassB */
}
}
仅当ClassA
具有多态性(即,它至少有一个虚函数)时,这些才有效。
答案 5 :(得分:2)
Slighlty与你要求的不同
ClassB* b;
if ((b = dynamic_cast<ClassB*>(ptr)) == 0) {
// not a classB*
} else {
// a classB* in b
}