我想比较两个派生自相同基类型但不是相同派生类的对象。所以我将==运算符设为虚拟并将其覆盖在派生类中。
当我将所有对象存储在基类型的数组中时,不会调用派生的实现,而是直接进入基本实现。但是,当数组是指向基类的类型指针,并且取消引用元素时,它确实有效。
请问某人请解释为什么会出现这种情况?它令我感到困惑; - )
enum eType {
BASE_TYPE,
DERIVED_TYPE
};
class A {
eType mType;
public:
A() : mType(BASE_TYPE) {}
A(eType Type) : mType(Type) {}
virtual bool operator == (A &Other) {
return mType == Other.mType;
}
};
class B : public A {
int bVal;
public:
B(int Val) : A(DERIVED_TYPE), bVal(Val) {}
virtual bool operator == (A &Other) {
if(!(A::operator ==(Other))) {
return false;
}
B* myB = (B*)&Other;
return bVal == myB->bVal;
}
};
int main(int argc, char *argv[])
{
A a1, a2;
B b1(0);
B b2(1);
bool result = false;
// Calls implementation in A
result = (a1 == a2);
// Calls implementation in B
result = (b1 == b2);
A aArray[2];
aArray[0] = b1;
aArray[1] = b2;
// Calls implementation in A!
result = (aArray[0] == aArray[1]);
A *aRefArray[2];
aRefArray[0] = &b1;
aRefArray[1] = &b2;
// Calls implementation in B
result = ((*aRefArray[0]) == (*aRefArray[1]));
return 0;
}
答案 0 :(得分:5)
A aArray[2];
aArray[0] = b1;
aArray[1] = b2;
当您这样做时,会发生 Object Slicing ,并且会剥离对象的派生部分。现在存储在数组中的对象现在只是作为Base类的对象。当然,调用operator函数的Base类版本。
A *aRefArray[2];
aRefArray[0] = &b1;
aRefArray[1] = &b2;
适当地,保留派生类对象的type
,因为存储在数组中的内容只是指向实际对象而不是对象本身的指针。
由于保留了对象的类型,因此在这种情况下将调用操作符函数的派生类版本。