出于我的目的,我尝试包装类似于 Qt 共享数据指针的东西,经过测试,我发现当应调用 const 函数时,会选择其非 const 版本。
我正在使用 C++0x 选项进行编译,这是一个最小的代码:
struct Data {
int x() const {
return 1;
}
};
template <class T>
struct container
{
container() {
ptr = new T();
}
T & operator*() {
puts("non const data ptr");
return *ptr;
}
T * operator->() {
puts("non const data ptr");
return ptr;
}
const T & operator*() const {
puts("const data ptr");
return *ptr;
}
const T * operator->() const {
puts("const data ptr");
return ptr;
}
T* ptr;
};
typedef container<Data> testType;
void testing() {
testType test;
test->x();
}
如您所见,Data.x 是一个 const 函数,因此调用的运算符 -> 应该是 const 函数。当我注释掉非常量时,它编译时没有错误,所以这是可能的。但我的终端打印:
“非常量数据指针”
这是一个 GCC 错误(我有 4.5.2),还是我遗漏了什么?
如果您有两个仅在
const
性质上有所不同的重载,则编译器将根据 *this
是否为 const
来解析调用。在您的示例代码中, test
不是 const
,因此调用非 const
重载。
如果您这样做:
testType test;
const testType &test2 = test;
test2->x();
您应该看到另一个重载被调用,因为
test2
是 const
。
test
是一个非常量对象,因此编译器会找到最佳匹配:非常量版本。不过,您可以使用 static_cast
应用常量: static_cast<const testType&>(test)->x();
编辑:顺便说一句,正如您怀疑 99.9% 的时间您认为自己发现了编译器错误一样,您应该重新访问您的代码,因为可能存在一些奇怪的怪癖,而编译器实际上遵循标准。
Data::x
是否是常数函数并不重要。被调用的运算符属于 container<Data>
类而不是 Data
类,并且其实例不是常量,因此调用非常量运算符。如果只有常量运算符可用或者类的实例本身就是常量,则将调用常量运算符。
但是
testType
不是 const 对象。
因此它将调用其成员的非常量版本。
如果这些方法具有完全相同的参数,则必须选择调用哪个版本(因此它使用 this 参数(隐藏的参数))。在这种情况下,这不是 const,因此您将获得非常量方法。
testType const test2;
test2->x(); // This will call the const version
这不会影响对 x() 的调用,因为您可以在非 const 对象上调用 const 方法。