Question

I was surprised to find this "hole" in "const"ness:

#include <stdio.h>

class A
{
  int r ;
public:
  A():r(0){}

  void nonconst()
  {
    puts( "I am in ur nonconst method" ) ;
    r++;
  }
} ;

class B
{
  A a ;
  A* aPtr ;

public:
  B(){ aPtr = new A() ; }

  void go() const
  {
    //a.nonconst() ;      // illegal
    aPtr->nonconst() ;  //legal
  }
} ;

int main()
{
  B b ;
  b.go() ;
}

So basically from const method B::go(), you can invoke the non-const member function (aptly named nonconst()) if object of type A is referenced by a pointer.

Why is that? Seems like a problem (it kind of was in my code, where I found it.)

Was it helpful?

Solution

When and object of type B is const, then all of its members are const, which means its two members are, for the duration of B::go(), effectively

A const a;
A * const aPtr;

The first is a constant object of type A, on which you can only call const member functions. The second, however, is a constant pointer to a non-constant A. You could not legally say aPtr = <anything> from within the function B::go(), since that would modify aPtr, which is constant.

A pointer to a constant A would be declared as A const* aPtr or const A* aPtr, which would then make calling the non-constant A::nonconst() illegal.

OTHER TIPS

The "const-ness" of an object does not extend to other objects through pointers. In your example, the const part is either the entire object a, or the pointer aPtr. Because aPtr is a A * and not a const A *, you are allowed to call a non-const method.

If you change

A* aPtr ;

to

const A* aPtr ;

then you will not be able to call aPtr->nonconst().

Language definition of const

I was surprised to find this "hole" in "const"ness:

There is none.

const applies uniformly to all class members: in a const member function of class C, this has type const C *, so for a member C::mem declared as type T:

class C {
// ...
    T mem;
};

this->mem has type const T.

Please take type to discern what is the declared type T and the corresponding const-qualified type for all the members.

Seems like a problem (it kind of was in my code, where I found it.)

Just because the systematic application of rules does not do what you expected does not mean there is a problem with the rules, it means there is a problem with your expectations.

You should write down your expectations to see that you expected a non uniform application if const to different types.

When you program, you have to reason logically. You should infer things, not expect them when there is no logical reason.

Using const correctly

Why is that?

Your classes being called A and B, it's pretty hard to understand what constitute logical state and what does not. ;) You ask a "moral" question (not a question only on legal/illegal C++ programs), and your code fragment has no "moral" value. If you actually post relevant code, we might make some "moral" judgements about it.

Logical state

You should declare const the functions that do not change the "logical state" of the object it's applied to.

It means you have to define what is the "logical state" of your class instances: it's an abstract concept, and only you can define it, because it's a high level concept. The "logical state" relates to the problem your class should solve.

Then you can discern which variables contribute to the logical state: does *(b.aPtr) contribute to the logical state of b?

Closely related questions

Do you know about the copy constructor?

About the copy assignment operator?

About the destructor?

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