2011-10-04 38 views
0

我想比较两个派生自相同基本类型但派生类不相同的对象。所以我使得==运算符是虚拟的,并在派生类中重载它。比较运算符的C++多态性按值和引用

当我将所有对象存储在基本类型的数组中时,派生实现不会被调用,它会直接转到基本实现。但是,当数组的类型是指向基类的指针并且取消引用元素时,它确实有效。

有人可以解释为什么会出现这种情况吗?这令我感到困惑;-)

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

您是否期望比较不同类型的物体? –

+1

切片的问题在[这个问题]中已经介绍过(http://stackoverflow.com/questions/4403726/learning-c-polymorphism-and-slicing)。 –

+0

请注意,在切片问题旁边,比较和多态不是那么直截了当,因为多态主要是关于让对象执行某些操作。有dynamic_cast和双重调度的解决方案,但它并不简单。 – stefaanv

回答

5
A aArray[2]; 
    aArray[0] = b1; 
    aArray[1] = b2; 

当你这样做Object Slicing发生和对象的派生部分只是获取剥去。现在存储在数组中的对象现在仅仅表现为基类的对象。当然,运算符函数的基类版本被调用。


A *aRefArray[2]; 
    aRefArray[0] = &b1; 
    aRefArray[1] = &b2; 

适当地,保留了派生类对象的type,因为什么都存储在阵列中只是指向实际的对象不是对象本身。
由于保留了对象的类型,因此在这种情况下调用操作符函数的派生类版本。