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_cast
从const DerivedContainer *
到BaseContainer *
是非法的,我不确定这是否适用于多态性。
我假设转换仍然有效,因为 this
的类型在 BaseContainer::operator[] const
中总是 const BaseContainer *
因为它不是虚拟的,但我不确定那是否是这样做的正确方法。也许在这种情况下定义两次 operator[]
更好?
would assume that the const_cas
t 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
。否则你会得到未定义的行为。
我有一个常量重载的访问器成员函数(例如 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_cast
从const DerivedContainer *
到BaseContainer *
是非法的,我不确定这是否适用于多态性。
我假设转换仍然有效,因为 this
的类型在 BaseContainer::operator[] const
中总是 const BaseContainer *
因为它不是虚拟的,但我不确定那是否是这样做的正确方法。也许在这种情况下定义两次 operator[]
更好?
would assume that the
const_cas
t is still valid because the type of this would always beconst BaseContainer *
inBaseContainer::operator[] const
because it is notvirtual
, 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
。否则你会得到未定义的行为。