Reputation: 598
Are these definitions of pointer()
equal?
class Example
{
public:
AnotherClass* const pointer() const;
AnotherClass* pointer() const;
private:
AnotherClass* m_pointer;
}
Does it guarantee me what somebody can't change m_pointer memory pointed to?
Upvotes: 0
Views: 161
Reputation: 20503
There are a few things to consider here:
What is const
: the pointer or the pointee?
Let's see the differences between these different declarations.
int x, y;
int * p = &x; // 0
const int * p = &x; // 1
int const * p = &x; // 2
int * const p = &x; // 3
const int * const p = &x; // 4
int const * const p = &x; // 5
(0) means that p
can change (p = &y;
is OK) and what it points to (x
) can be changed via p
(*p = y;
is OK).
(1) and (2) are equivalent and mean that p
can change (p = &y;
is OK) and what it points to (x
) cannot be changed via p
(*p = y;
is an error).
(3) means that p
cannot change (p = &y;
is an error) and what it points to (x
) can be changed via p
(*p = y;
is OK)
(4) and (5) are equivalent and mean that p
cannot change (p = &y;
is an error) and what it points to (x
) cannot be changed via p
(*p = y;
is an error).
An easy way to remember this is looking at the *
and think that it separates the objects constness, that is,
(a) a const
before *
(e.g. const int * [...]
or int const * [...]
) means the pointed object (of type int
) is const
; and
(b) a const
after *
(e.g. [...] * const p [...];
) means that the pointer is const
and cannot be changed.
What happens if a function returns a const
object?
Consider:
class some_class;
const some_class a(); // equivalent to 'some_class const a();'
someclass b();
const int c(); // equivalent to 'int const c();'
int d();
Then, (assuming some_class
has an accessible assignment operator) we have:
some_class x;
a() = x; // illegal : the returned object is const
b() = x; // OK : the returned object is not const
It's natural to believe that c()
and d()
behave the same but this is not the case:
c() = 0; // illegal
d() = 0; // also illegal!!!
The reason is that if a function returns a fundamental type (e.g. int
, bool
, char
, any pointer type, ...) then the returned object cannot be assigned to. Therefore,
returning a const
object of fundamental type behaves the same as to returning a non-const one.
What about overloading on the return type?
Consider
int f(); // first overload.
double f(); // second overload.
This is illegal. We cannot overload on the return type only. One reason is that we can always ignore the object returned by a function. For instance, if overloading on the return type was allowed, then which overload of f
would be called below?
int main() {
f(); // which f?
return 0;
}
Answering the question...
Consider the first declaration
AnotherClass* const pointer() const;
From what we have seen, this means that pointer()
returns a const
object of type AnotherClass*
(a pointer type). Since a pointer type is a fundamental type, the function pointer
above behaves the same as if it was declared as
AnotherClass* pointer() const;
which is the second overload. This is the first reason why having these two overloads doesn't make sense. But this is just a weak reason compared to the one that follows.
When I say "behaves the same" I don't mean "equivalent". The return type of the two overloads are different. As we have seen, we cannot overload on the return type only. This is illegal and the code doesn't compile.
Does it guarantee me what somebody can't change m_pointer memory pointed to?
No, again, both overloads behave the same and return a pointer to an object that can be changed via this pointer. What you want is this:
const AnotherClass* pointer() const { return m_pointer; }
// or
// AnotherClass const* pointer() const { return m_pointer; }
Notice the const
at the left of *
.
Upvotes: 1
Reputation: 16726
The two overloads for pointer
only differ in the return type. Your C++ compiler will not accept that, this is an error.
Assuming that pointer() just returns m_pointer:
The declaration AnotherClass* pointer() const;
would expose the value of m_pointer. Users of the class would not be able to change m_pointer, but they could change the object that m_pointer points to.
The declaration AnotherClass* const pointer() const;
is quite similar to AnotherClass* pointer() const;
but the value returned (the temporary pointer) is const. This declaration does not really make sense because you already can't change the return value in the first declaration. You can't write example.pointer() = nullptr
in either cases. And when you assign the return value to a variable like in p = example.pointer()
it makes no difference if the return value of pointer() is const or not.
The declarations const AnotherClass* pointer() const;
and AnotherClass const * pointer() const;
would expose the value of m_pointer. Users of the class would not be able to change m_pointer, and they would not be able to change the object that m_pointer points to.
Upvotes: 1
Reputation: 1806
You need the return type for the first method to be one of these:
AnotherClass const * pointer() const;
or
const AnotherClass* pointer() const;
What you have done is return a const pointer to a non-const object.
What you want is a non-const pointer to a const object.
Also, to follow the typical practice your second method should not be const.
AnotherClass* pointer();
Upvotes: 2