1

Suppose we have a following piece of code:

class Base {
  public:
    int a = 5;
};

class Derived : public Base {
  public:
    Base *parent_ = new Base;
    Base* parent() const { return parent_; }
};

void f(const Derived *derived) {
    Base *p = derived->parent();
    p->a = 10; // <- is this correct?
}

Personally I think here is a problem:

In function f we take a pointer to const object of class Derived. This makes each member of it also const thus parent_ becomes const Base *. If it is const we should not have an ability to modify the object on which the pointer points.

Where am I wrong?

VP.
  • 15,509
  • 17
  • 91
  • 161
  • `int a = 5;` - is this C++11? – sashoalm May 18 '16 at 09:37
  • 2
    `parent_` is of type `Base * const`, not `const Base *`. – Quentin May 18 '16 at 09:37
  • @sashoalm yes, it is. But I did not tag the question with `c++11` because it is irrelevant. – VP. May 18 '16 at 09:38
  • 1
    @sashoalm [yes](http://stackoverflow.com/questions/13662441/c11-allows-in-class-initialization-of-non-static-and-non-const-members-what-c). – Quentin May 18 '16 at 09:38
  • @VictorPolevoy the [c++] tag designates the latest standard, that is C++14 for now. So that's fine. – Quentin May 18 '16 at 09:39
  • @Quentin well, nice, thanks, did not know that. Well, people still want to add these tags which does not makes the question any better :/ Lol, here is a war, one makes an edit with tags `c++11` and `c++14`, other deletes them both, funny to see :) – VP. May 18 '16 at 09:41
  • 4
    btw the question is not really specific to inheritance. Imho it would be better edit and remove any inheritance stuff – 463035818_is_not_an_ai May 18 '16 at 09:43
  • @tobi303 I am not best at looking for the words to say but is not that some kind of synonym of "inheritance"? – VP. May 18 '16 at 09:46
  • 1
    well there is inheritance in your code, but the problem is not caused by that. The answers dont even mention inheritance. Imho better title would be "Clarify const qualifier when returning pointer" – 463035818_is_not_an_ai May 18 '16 at 09:49
  • 1
    @VictorPolevoy : tobi303 was referring to `Derived` inheriting from `Base` in your code sample - that has no impact on your question, and in fact can cause some confusion with the use of `Base` as both a base class and a member. – Sander De Dycker May 18 '16 at 09:49
  • 1
    @VictorPolevoy the usual term for this mechanism is *const propagation*. – Quentin May 18 '16 at 09:49

4 Answers4

7

This makes each member of it also const thus parent_ becomes const Base *.

No, the pointer will become const itself, not the object it points to. So parent_ becomes Base * const, not const Base *, and your code is valid.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
5
Base* parent() const { return parent_; }

Unfortunately, this is problem with C++. Method is const, but it is returning a non-const pointer, which would allow following operation to succeed:

p->a = 10; // <- is this correct?

It is programmer's responsibility not to return non-const pointer or references from functions (method being const or not).

Ajay
  • 18,086
  • 12
  • 59
  • 105
  • According to @songyuanyao 's answer this is not a problem since we change the object which remains `non-const` because the only thing that becomes `const` by `const propagation` is the pointer itself. – VP. May 18 '16 at 09:55
  • @VictorPolevoy I'd say it is a problem. You're not breaking the language, but you're breaking logical constness. – TartanLlama May 18 '16 at 10:21
0

As tobi303 points out below, this answer is wrong. Keeping it here for the sake of the discussion below.


I could be wrong, but this line:

    Base* parent() const { return parent_; }

does not mention anything about returning const objects. It is equivalent to

    Base* parent() const { return this->parent_; }

where this is const Derived*, but parent_ is still Base*.

Vorac
  • 8,726
  • 11
  • 58
  • 101
  • 3
    the member of a `const` object is also `const`, otherwise the whole `const` story would be useless for public members – 463035818_is_not_an_ai May 18 '16 at 09:50
  • 1
    @tobi303 you seem to not understand the difference between `const T *` and `T * const` – M.M May 18 '16 at 09:52
  • 2
    `this` is `const Derived* const`, `parent_` is `Base* const`. – songyuanyao May 18 '16 at 09:53
  • @M.M i do understand the difference. but as songyuanyao pointed out, if `this` is `const` then also its member `parent_` is `const`. As the member is a pointer, as a member of a `const` object it becomes a `const` pointer (pointing to a non-const object). Actually it wasnt my intention to call this answer "wrong".... – 463035818_is_not_an_ai May 18 '16 at 11:08
  • @tobi303, I am actually thankful that you corrected me. Maybe a concise version of the current discussion should be edited into the accepted answer. – Vorac May 18 '16 at 12:44
0

A const method only prevents the method from modifying any non-mutable data members of the class.

If you want to not allow the modification of a and don't want to update the class, you need to write:

const Base *p = derived->parent();

However, I would recommend you to not return non-const data members from a class as ref or pointer because this breaks the data encapsulation concept of C++. This is the same, of course, with the public a.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
cpow
  • 476
  • 4
  • 8