Calling a const function rather than its non-const version
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. An开发者_JS百科d 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?
If you have two overloads that differ only in their const
-ness, then the compiler resolves the call based on whether *this
is const
or not. In your example code, test
is not const
, so the non-const
overload is called.
If you did this:
testType test;
const testType &test2 = test;
test2->x();
you should see that the other overload gets called, because test2
is const
.
test
is a non-const object, so the compiler finds the best match: The non-const version. You can apply constness with static_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.
It doesn't matter whether Data::x
is a constant function or not. The operator being called belongs to container<Data>
class and not Data
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.
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.
testType const test2;
test2->x(); // This will call the const version
This does not affect the call to x() as you can call a const method on a non const object.
精彩评论