为什么调用非 const 成员函数而不是 const 成员函数?
为了我的目的,我尝试包装一些类似于 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 函数,因此运算符 ->被调用的应该是 cons 。当我注释掉非常量时,它编译时没有错误,所以这是可能的。然而我的终端打印:
“非常量数据指针”
这是一个 GCC bug(我有 4.5.2),还是我遗漏了什么?
I tried to wrap something similar to Qt's shared data pointers for my purposes, and upon testing I found out that when the const function should be called, its non-const version was chosen instead.
I'm compiling with C++0x options, and here is a minimal code:
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();
}
As you can see, Data.x is a const function, so the operator -> called should be the const one. And when I comment out the non-const one, it compiles without errors, so it's possible. Yet my terminal prints:
"non const data ptr"
Is it a GCC bug (I have 4.5.2), or is there something I'm missing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您有两个仅在
const
性质上有所不同的重载,则编译器会根据*this
是否为const
来解析调用。在您的示例代码中,test
不是const
,因此调用非const
重载。如果您这样做:
您应该看到另一个重载被调用,因为
test2
是const
。If you have two overloads that differ only in their
const
-ness, then the compiler resolves the call based on whether*this
isconst
or not. In your example code,test
is notconst
, so the non-const
overload is called.If you did this:
you should see that the other overload gets called, because
test2
isconst
.test
是一个非常量对象,因此编译器会找到最佳匹配:非常量版本。不过,您可以使用static_cast
应用常量:static_cast(test)->x();
编辑:顺便说一句,正如您怀疑的 99.9%当您认为发现了编译器错误时,您应该重新访问代码,因为可能存在一些奇怪的怪癖,而编译器实际上遵循标准。
test
is a non-const object, so the compiler finds the best match: The non-const version. You can apply constness withstatic_cast
though:static_cast<const testType&>(test)->x();
EDIT: As an aside, as you suspected 99.9% of the time you think you've found a compiler bug you should revisit your code as there's probably some weird quirk and the compiler is in fact following the standard.
Data::x
是否是常量函数并不重要。被调用的运算符属于container
类而不是Data
类,并且其实例不是常量,因此调用非常量运算符。如果只有常量运算符可用或者类的实例本身就是常量,则将调用常量运算符。It doesn't matter whether
Data::x
is a constant function or not. The operator being called belongs tocontainer<Data>
class and notData
class, and its instance is not constant, so non-constant operator is called. If there was only constant operator available or the instance of the class was constant itself, then constant operator would have been called.但 testType 不是 const 对象。
因此它将调用其成员的非常量版本。
如果这些方法具有完全相同的参数,则必须选择调用哪个版本(因此它使用 this 参数(隐藏的参数))。在本例中,这不是 const,因此您将获得非常量方法。
这不会影响对 x() 的调用,因为您可以在非 const 对象上调用 const 方法。
But
testType
is not a const object.Thus it will call the non const version of its members.
If the methods have exactly the same parameters it has to make a choice on which version to call (so it uses the this parameter (the hidden one)). In this case this is not const so you get the non-const method.
This does not affect the call to x() as you can call a const method on a non const object.