Invoking a nonconst method on a member from a const method

最后都变了- 提交于 2019-11-30 08:37:48

问题


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


回答1:


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.




回答2:


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




回答3:


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?



来源:https://stackoverflow.com/questions/8556794/invoking-a-nonconst-method-on-a-member-from-a-const-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!