Question

In following example const object can modify itself via const method, because in that method it acces itself via non-const pointer. (same program on ideone)

#include <iostream>

struct Object;

Object * g_pObject;

struct Object
{
    Object():m_a(0){}

    void ModifySelfViaConstMethod() const
    {
        g_pObject->m_a = 37;
    }

    int m_a;
};

int main()
{
    Object o;
    g_pObject = &o;

    const Object & co = o;
    std::cout << co.m_a << "\n";
    co.ModifySelfViaConstMethod();
    std::cout << co.m_a << "\n";

    return 0;
}

I am not so good with reading c++ standard, so I ask here:

What does standard says about this?

a)const method doesn't guarantee you that your object stays unmodified when you do stuff like this

b) Is it well defined that and it must compile

c) other ?

Was it helpful?

Solution

What does standard says about this?

It says (paraphrasing) that this has type const Object *, so that you can't directly modify members or call non-const member functions via this. It says nothing about what you can do with any global variables that the function might have access to; it only controls direct access to the object the function is called on.

const method doesn't guarantee you that your object stays unmodified when you do stuff like this

No it doesn't. It states the intent that the function won't modify the object, and provides some protection against accidentally breaking that intent. It doesn't prevent a suitably deranged programmer from using const_cast, or (as here) uncontrolled coupling via global variables to break the promise.

Is it well defined that and it must compile

Yes. o is not itself constant, so there's nothing to stop you taking a non-const pointer or reference to it. The const on the member function only restricts access to the object via this, not to arbitrary objects via other pointers.

OTHER TIPS

When you declare a const function, it's "for your own good".

In other words, you declare it const because according to your initial design, it is not supposed to change any object with which it will be invoked during runtime.

If during some later point in the implementation of this function you end up changing the object, the compiler will "yell at you", telling you it's wrong.

Of course, the compiler will be able to identify such attempt, only when applied on this.

In the given example, the compiler cannot identify the problem because it requires a comparison between this and g_pObject, and such comparison can only take place during runtime.

When a method is declared as const, the compiler ensures that the instance pointed to by the this pointer is not modified. If you try to modify the this instance, the compiler to fail. However, the compiler has no way of knowing that g_pObject and this are actually pointing at the same instance. That requires a run-time comparison, and no compiler is going to waste time performing run-time comparisons of every pointer used inside of a const method in the off-chance that they might match the this pointer. So if you are going to modify an Object via an external pointer, you are going to have to do your own check, eg:

void ModifySelfViaConstMethod() const
{
    if (g_pObject != this)
        g_pObject->m_a = 37;
}

Constancy in C++ is a safety instrument, not security.

The code where constancy is honored will most probably work as expected, and all unintentional attempts to cast constancy away will be alerted by the compiler.

In cases when "I know what I am doing" one can find the whole variety of tools, from const_cast operator and mutable keyword to the banal C style cast.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top