问题
Why won't the method getRanks()
below compile, and how can I fix it gracefully?
All I want do is define a member accessor method that returns a reference to a member. The reference is not const
since I might well modify what it refers to later. But since the member method does not modify the object, I declare it const
. The compiler (clang, std=c++11) then insists that there is a "binding of reference" that "drops qualifiers". But I'm NOT dropping qualifiers, am I? And if I am, why:
struct teststruct{
vector<int> ranks;
vector<int>& getRanks()const{
return ranks;
}
};
Now, the code compiles if I change the return statement to cast away the const:
return const_cast<vector<int>&>(ranks);
But "ranks" should not be const in the first place, I don't see why I need to const_cast the const away. I don't even know if it's safe to do this.
Anyway, is there a cleaner to write this method? Can someone explain why such a simple common-sense method fails? I do want to declare the getRanks()
method "const
" so that I can call it from other const
methods.
回答1:
The idea behind the const
member function is you should be able to call them on const
objects. const
functions can't modify the object.
Say you have a class
class A
{
int data;
void foo() const
{
}
};
and on object and a function call:
A const a;
a.foo();
Inside A::foo
, this->data
is treated as if its type is int const
, not int
. Hence, you are not able to modify this->data
in A:foo()
.
Coming to your example, the type of this->ranks
in getRanks()
is to be considered as const vector<int>
and not vector<int>
. Since, auto conversion of const vector<int>
to vector<int>&
is not allowed, the compiler complains when you define the function as:
vector<int>& getRanks()const{
return ranks;
}
It won't complain if you define the function as:
const vector<int>& getRanks()const{
return ranks;
}
since const vector<int>
can be auto converted to const vector<int>&
.
回答2:
ranks
is const
because the enclosing object (*this
) is const
, so you have to return a reference to a std::vector<int> const
.
If you want to allow the client to modify the vector (and thereby affecting the member), then the getter should not be const
. Note that the getter is silly anyway, since ranks
is already a public data member.
回答3:
You are returning a reference to ranks
, which is a member of teststruct
. That means that anybody that gets this reference could modify the internals of the teststruct
object. So the const
is a lie.
Don't cast away the const
. Instead, decide between whether you want the function to be const
and return a copy of ranks
or const
reference, or to be non-const
and return a mutable reference. You can always have both if necessary.
回答4:
It drops qualifiers because you return a reference to ranks
. Any code after can modify ranks. Ex:
auto v = teststruct.getRanks();
v[1] = 5; //assuming v.size() > 1
You can fix this by returning a copy:
vector<int> getRanks() const
Or a const
reference:
const vector<int>& getRanks() const
If you want ranks
changable even in a const
object, you could do this:
mutable vector<int> ranks;
来源:https://stackoverflow.com/questions/24346563/why-cant-a-const-method-return-a-non-const-reference