从const方法对成员调用nonconst方法

时间:2011-12-19 03:23:24

标签: c++ pointers const const-correctness

我很惊讶地发现“const”中的这个“漏洞”:

#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() ;
}

所以基本上从const方法B::go()开始,如果类型为{{1}的对象,则可以调用非const 成员函数(恰当地命名为nonconst())由指针引用。

为什么?看起来像是一个问题(它在我的代码中,我找到了它。)

3 个答案:

答案 0 :(得分:11)

何时类型B的对象是const,那么它的所有成员都是const,这意味着它的两个成员在B::go()期间有效

A const a;
A * const aPtr;

第一个是A类型的常量对象,您只能在其上调用const成员函数。然而,第二个是指向非常数A的常量指针。您无法在函数aPtr = <anything>内合法地说B::go(),因为这会修改aPtr,这是常量。

指向常量A的指针将被声明为A const* aPtrconst A* aPtr,这会使调用非常量A::nonconst()非法。

答案 1 :(得分:6)

对象的“常量”通过指针扩展到其他对象。在您的示例中,const部分是整个对象a,或指针 aPtr。由于aPtrA *而不是const A *,因此您可以调用非const方法。

如果你改变了

A* aPtr ;

const A* aPtr ;

然后您将无法拨打aPtr->nonconst()

答案 2 :(得分:0)

const

的语言定义
  

我很惊讶地发现“const”中的这个“漏洞”:

没有。

const统一应用于所有班级成员:在班级const的{​​{1}}成员函数中,C的类型为this },因此对于声明为const C *类型的成员C::mem

T

class C { // ... T mem; }; 的类型为this->mem

请使用type来识别所有成员的声明类型const T和相应的const限定类型。

  

看起来像是一个问题(它出现在我的代码中,我找到了它。)

仅仅因为系统应用规则没有达到您的预期并不意味着规则存在问题,这意味着您的期望存在问题。

如果T属于不同类型,您应该写下您的期望,以确保您预期会出现非统一的申请。

编程时,你必须在逻辑上进行推理。你应该推断出事物,在没有合理逻辑的情况下不要指望它们。

正确使用const

  

为什么?

您的课程被称为constA,很难理解什么是逻辑状态,什么不是。 ;)你问一个“道德”问题(不只是关于合法/非法C ++程序的问题),而你的代码片段没有“道德”价值。如果您实际发布相关代码,我们可能会做出一些“道德”判断。

逻辑状态

您应该声明B不会更改其应用对象的“逻辑状态”的函数。

这意味着你必须定义类实例的“逻辑状态”:它是一个抽象的概念,只有你可以定义它,因为它是一个高级概念。 “逻辑状态”与您的课程应解决的问题有关。

然后你可以看出哪些变量对逻辑状态有贡献:const是否有助于*(b.aPtr)的逻辑状态?

密切相关的问题

你知道复制构造函数吗?

关于复制赋值运算符?

关于析构函数?