C++ 常数重载与多形性

C++ 常数重载与多形性,c++,polymorphism,overloading,return-by-reference,C++,Polymorphism,Overloading,Return By Reference,我有一个常量重载的访问器成员函数(例如,运算符[]): 类容器{ 公众: Foo&operator[](国际一级); 常量Foo和运算符[](int i)常量{ 返回const_cast(this)->运算符[](i); } }; 这里,const-Foo&operator[]const是这样定义的,因此同一事物不会被定义两次 现在我想将容器作为一个基类,并且操作符[]变成虚拟的: 类基本容器{ 公众: 虚拟Foo&操作符[](int i)=0; 常量Foo和运算符[](int i)常量{ /

我有一个常量重载的访问器成员函数(例如,
运算符[]
):

类容器{
公众:
Foo&operator[](国际一级);
常量Foo和运算符[](int i)常量{
返回const_cast(this)->运算符[](i);
}
};
这里,
const-Foo&operator[]const
是这样定义的,因此同一事物不会被定义两次

现在我想将
容器
作为一个基类,并且
操作符[]
变成虚拟的:

类基本容器{
公众:
虚拟Foo&操作符[](int i)=0;
常量Foo和运算符[](int i)常量{
//这是正确的吗?
返回const_cast(this)->运算符[](i);
}
};
类DerivedContainer:公共BaseContainer{
公众:
Foo&operator[](国际一级);
};
由于从
const-DerivedContainer*
BaseContainer*
进行
const-cast
是非法的,我不确定这在多态性的情况下是否有效

我假设强制转换仍然有效,因为
this
的类型在
BaseContainer::operator[]const
中始终是
const BaseContainer*
,因为它不是虚拟的,但我不确定这样做是否正确。在这种情况下,最好定义两次
操作符[]

假设
const\u cas
t仍然有效,因为它的类型始终是
BaseContainer::operator[]const
中的
const BaseContainer*
,因为它不是
virtual
,但我不确定这样做是否正确

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

不过,还有一件事你必须考虑。当你申报时

Foo& operator[](int i);
在派生类中,如果对派生类对象/引用/指针进行函数调用,则找不到
const
版本。为了能够将其与派生类对象/引用/指针一起使用,请在派生类中添加以下内容

using BaseContainer::operator[];

由于多态性,将从
BaseContainer::const操作符[]
的主体调用
DerivedContainer
中重载的非常量版本。因此,从这一点来看,它实际上是一种“合法”设计,尽管您的假设“这将始终是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;
}
struct Base{

virtual void print(){cout
//是否正确?
-否。请尝试以下操作:
const-DerivedContainer;Foo&f=dc[42]
。看到问题了吗?进一步说:除非你能保证其引用'const_cast'从中剥离const ness的原始对象实际上在开始时是非const的,否则你在玩火。不确定我是否遗漏了什么,但是
const Foo&operator[](int I)中的
这个
由于多态性,const
可能仍然是一个
DerivedContainer*
。@StephanLechner,当然可以。但这应该不是问题。