我有一个const重载的访问器成员函数(例如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_cast
到const DerivedContainer *
的{{1}}是非法的,因此我不确定在多态的情况下是否可行。
我认为类型转换仍然有效,因为BaseContainer *
中的this
类型始终是const BaseContainer *
,因为它不是虚拟的,但是我不确定这是否正确这样的方式。在这种情况下,也许最好两次定义BaseContainer::operator[] const
?
答案 0 :(得分:4)
将假设
const_cas
t仍然有效,因为在const BaseContainer *
中,此类型始终为BaseContainer::operator[] const
,因为它不是virtual
,但我不确定如果这是正确的方法。
您的理解是正确的。该代码应按预期工作。
但是,您还需要考虑另一件事。当您声明
Foo& operator[](int i);
在派生类中,如果在派生类对象/引用/指针上进行函数调用,将找不到const
版本。为了能够与派生类对象/引用/指针一起使用,请在派生类中添加以下内容。
using BaseContainer::operator[];
答案 1 :(得分:0)
由于多态性,DerivedContainer
中重载的非const版本将从BaseContainer::const operator[]
的主体中调用。因此,从这一点来看,它实际上是一种“合法”的设计,尽管您的假设“在多态性的情况下,它始终是const BaseContainer *在BaseContainer :: operator [] const中,因为它不是虚拟的”,这是错误的。>
请参见以下说明呼叫链的代码:
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[]
的非常量主体最初已定义为*this
,则不得更改const
对象。否则,您将获得不确定的行为。