Const 重载和多态性

Const overloading and polymorphysm

我有一个常量重载的访问器成员函数(例如 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设为基class,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[] 更好?

would assume that the const_cast is still valid because the type of this would always be const BaseContainer * in BaseContainer::operator[] const because it is not virtual, but I am not sure if that's the correct way of doing this.

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

不过,您还需要考虑另一件事。当你声明

Foo& operator[](int i);

在派生 class 中,如果函数调用是在派生 class object/reference/pointer 上进行的,则不会找到 const 版本。为了能够将其与派生 class object/reference/pointer 一起使用,请在派生 class.

中添加以下内容
using BaseContainer::operator[];

由于多态性,DerivedContainer 中重载的 non-const-version 将从 BaseContainer::const operator[] 的主体中调用。所以从这一点来看,它实际上是一个 "legal" 设计,尽管你的假设 "this would always be const BaseContainer * in BaseContainer::operator[] const because it is not virtual" 在多态性的上下文中是错误的。

请参阅以下说明调用链的代码:

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;
}

请注意,operator[] 的 non-const-body 不得更改 *this 对象,如果该对象最初被定义为 const。否则你会得到未定义的行为。