我试图为我的目的包装类似于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函数,因此运算符 - &gt;被叫应该是常数。当我注释掉非常量的那个时,它编译没有错误,所以它是可能的。然而我的终端打印:
“non const data ptr”
这是一个GCC错误(我有4.5.2),还是有什么我想念的?
答案 0 :(得分:24)
如果您有两个仅在const
- ness不同的重载,则编译器会根据*this
是否为const
来解析调用。在您的示例代码中,test
不是const
,因此调用非const
重载。
如果你这样做了:
testType test;
const testType &test2 = test;
test2->x();
你应该看到调用了另一个重载,因为test2
是const
。
答案 1 :(得分:9)
test
是一个非const对象,因此编译器找到最佳匹配:非const版本。您可以使用static_cast
来应用常量:static_cast<const testType&>(test)->x();
答案 2 :(得分:2)
Data::x
是否是常数函数并不重要。被调用的运算符属于container<Data>
类而不是Data
类,并且其实例不是常量,因此调用非常量运算符。如果只有常量运算符可用或者类的实例本身是常量,那么就会调用常量运算符。
答案 3 :(得分:0)
但是testType
不是const对象。
因此它将调用其成员的非const版本 如果方法具有完全相同的参数,则必须选择要调用的版本(因此它使用this参数(隐藏的参数))。在这种情况下,这不是const,因此您获得非const方法。
testType const test2;
test2->x(); // This will call the const version
这不会影响对x()的调用,因为您可以在非const对象上调用const方法。