Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoking a nonconst method on a member from a const method

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.)

like image 752
bobobobo Avatar asked Dec 19 '11 03:12

bobobobo


People also ask

Can a const member function call a non-const function?

const member functions have the following use cases: A const function can be called by either a const or non- const object. Only a non- const object can call a non- const function; a const object cannot call it.

Can you pass a non-const to a const?

For instance, you can pass non-const variables to a function that takes a const argument. The const-ness of the argument just means the function promises not to change it, whether or not you require that promise.

What will happen if a const object calls a non-const member function?

Since we can't call non-const member functions on const objects, this will cause a compile error.

Can a const function return a non-const reference?

If the thing you are returning by reference is logically part of your this object, independent of whether it is physically embedded within your this object, then a const method needs to return by const reference or by value, but not by non-const reference.


1 Answers

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.

like image 73
Dave S Avatar answered Sep 21 '22 02:09

Dave S