C++中非const调用const成员函数出现只读位置错误排查
问题分析与解决方案
你的编译错误根源在于基类qv的成员函数默认是private访问权限,导致派生类qq继承的非const版本operator[]无法被外部访问。当你调用q[3] = 2;时,编译器找不到public的非constoperator[],只能调用qq中public的const版本,返回const T&,自然无法赋值,从而抛出assignment of read-only location错误。
修复后的代码
只需要给qv类的成员函数加上public:访问修饰符即可:
template<class T> class qv { public: // 关键:添加public访问修饰符 virtual const T& operator[](int i) const = 0; T& operator[](int i) { return const_cast<T&>(static_cast<const qv*>(this)->operator[](i)); } }; template<class T> class qq : public qv<T> { public: const T& operator[](int i) const override { return this->data[i]; } protected: T data[5]; };
这样,非const版本的operator[]就变成了public成员,外部调用时会优先执行它,通过const版本的逻辑间接返回可修改的引用,赋值操作就能正常完成。
关于static_cast和const_cast的区别
这两个cast的职责完全不同,在这里的用法也各有道理:
static_cast<const qv*>(this):这是安全的编译期类型转换,用于将非const的this指针转换为const的基类指针,目的是调用const版本的operator[]。它会检查转换的合法性(比如派生类转基类是允许的),避免类型错误。const_cast<T&>(...):这是唯一能移除const属性的转换,在这里用来将const版本返回的const T&转换为T&。因为当前的operator[]是非const成员函数,this指向的是一个非const对象,所以这个转换是合法且安全的——我们明确知道底层对象是可修改的。
如果反过来用const_cast来转换this指针(比如const_cast<const qv*>(this)),虽然能达到同样的效果,但static_cast在类型检查上更严格,能避免潜在的类型错误,所以这里用static_cast是更规范的做法。
内容的提问来源于stack exchange,提问作者user2183336
相关产品推荐
相关产品推荐

