const超载和多晶状体

Const overloading and polymorphysm

本文关键字:晶状体 超载 const      更新时间:2023-10-16

i具有const-overpolagon的登录成员函数(例如 operator[](:

class Container {
public:
    Foo&       operator[](int i);
    const Foo& operator[](int i) const{
        return const_cast<Container *>(this)->operator[](i);
    }
};

在这里,const Foo& operator[] const以这种方式定义,因此未定义两次。

现在我想让Container成为基类,而operator[]变为虚拟:

class BaseContainer {
public:
    virtual Foo& operator[](int i) = 0;
    const Foo& operator[](int i) const{
        // Is this correct?
        return const_cast<BaseContainer *>(this)->operator[](i);
    }
};
class DerivedContainer : public BaseContainer {
public:
    Foo& operator[](int i);
};

由于const_castconst DerivedContainer *BaseContainer *是非法的,所以我不确定在多态性的情况下是否有效。

我认为铸件仍然有效,因为this的类型始终是BaseContainer::operator[] const中的const BaseContainer *,因为它不是虚拟的,但是我不确定这是否是正确的方法。也许在这种情况下两次定义operator[]是最好的?

会假设const_cas T仍然有效,因为它的类型始终是BaseContainer::operator[] const中的const BaseContainer *,因为它不是virtual,但是我不确定这是否是正确的方法。

您的理解是正确的。该代码应按预期工作。

不过,您必须考虑另一件事。当您声明

Foo& operator[](int i);

在派生类中,如果在派生的类对象/参考/指针上进行函数调用,则找不到const版本。要能够与派生的类对象/参考/指针一起使用,请在派生类中添加以下内容。

using BaseContainer::operator[];

由于多态性,DerivedContainer中CC_17中的过载的非cont-version将被调用。因此,从这一点开始,它实际上是一种"法律"设计,尽管您的假设"这始终是basecontainer :: operator [] const中的const basecontainer *,因为它不是虚拟的,因为它是 - 在多态性的背景下 - 错误。

请参阅以下说明呼叫链的代码:

struct Base {
    virtual void print() { cout << "Base.non-const;"; }
    void print() const { cout << "entry:Base.const;then..."; const_cast<Base *>(this)->print(); }
};
struct Derived : public Base {
    void print() override { cout << "Derived.non-const;"; }
};
int main() {
    const Base* bc = new Derived;
    bc->print();
    //Output: entry:Base.const;then...Derived.non-const;
    cout << endl;
    Base* bnc = new Derived;
    bnc->print();
    // Output: Derived.non-const;
}

请注意,如果该对象最初定义为const,则operator[]的非统计体不得更改*this -Object。否则您会得到未定义的行为。