const类型的成员函数内部如何改变成员变量

转自:http://blog.youkuaiyun.com/hsujouchen/archive/2009/08/02/4401304.aspx

 

通过指针也能实现。

 

 在C++中,由const修饰的成员函数的函数体内部,是不能够对成员变量进行修改的。这个特性被用来保证某些成员函数在实现过程中,避免由于程序员大意而对数据进行了错误的修改;同时也说明此成员函数是非修改性的。如只需要返回成员变量的成员函数就被声明为const类型(const的位置在函数定义参数列表之后)

      推广开来,在const成员函数中也不能够调用非const的成员函数。这是因为非const成员函数可能会改变成员变量的值,这与const成员函数的定义相违背。

      但是在某些情况下,需要在const函数中改变成员变量。这就需要把成员变量设置成mutable类型。如

  class C

  {

  public:

      void func(const int& p) const

      {

         i = p;

      }

  private:

    mutable int i;

};

    如果变量i不声明为mutable类型,则编译不会通过。

    如果成员变量是一个类类型或者结构类型,而在const函数中调用这些变量的成员函数,除了用mutable声明外,还可以用一种变通的方法:

  class D

 {

    public:

       void op(){}

 }

  class C

  {

  public:

      void func(const int& p, D& d) const

      {

         i = p;

         d.op();

      }

  private:

    mutable int i;

    D                cd;

  };

  然后在调用时,参数D& d以*this作为输入,也可以达到调用非const函数的作用。

  P.S 最近阅读相关的文章,又学到了一种方法,能够使得在const成员函数中调用非const成员函数。就是使用const_cast<>运算符。它能够使得const去掉const的属性,使得violate属性去掉violate属性。上面的例子就可以写成。

      void func() const

     {

          const_cast<D*>(&cd)->op();

     }

     同样能够编译通过。

<think>嗯,用户问的是const成员函数能否修改类的任何成员变量。我需要先回忆一下C++中const成员函数的基本概念。记得const成员函数是用来保证不修改对象状态的,对吧?那它们的this指针应该是指向const对象的,所以通过this指针访问的成员变量都不能被修改。 首先,要明确在const成员函数内部,所有非mutable的成员变量都不能被修改。比如,如果有成员变量是int或者普通类型的话,在const函数里是不能改的。但如果有成员被声明为mutable,那即使在const函数里也可以修改。比如有时候用于缓存或者计数器的情况。 然后,可能用户想知道有没有例外情况或者特殊情况。比如说,如果成员变量是指针的话,虽然指针本身不能被修改,但指针指向的内容是否可以修改呢?例如,一个指针成员int* data,在const函数里,data本身不能被重新赋值,但*data可以被修改。这种情况下,const成员函数虽然不能改变指针的指向,但可以改变指针指向的数据,这可能导致对象逻辑状态的变化,但编译器不会阻止,因为const只保证成员变量本身的值不变,而不涉及指向的内容。 另外,还有可能用户会混淆const成员函数和对象的常量性。比如,如果一个对象被声明为const,那么它只能调用const成员函数,这时候无论函数内部如何,都不能修改非mutable成员。但如果是非const对象调用const成员函数,同样遵循同样的规则。 有没有其他情况呢?比如通过const_cast去掉const属性?虽然技术上可以这样做,但这样做是未定义行为,应该避免。比如在const成员函数中,如果强制转换掉this的const属性,然后修改成员变量,这会导致不可预测的结果,所以绝对不推荐。 用户可能在实际编程中遇到需要修改某些成员的情况,比如缓存数据或者锁的状态,这时候应该使用mutable关键字来修饰这些变量,这样即使在const函数中也能修改它们。例如,在获取某个计算结果时,可能第一次计算后缓存结果,之后直接返回缓存值,这时候就需要在const函数里修改缓存的变量,所以用mutable。 总结的话,答案应该是const成员函数不能修改类的非mutable成员变量,但可以修改mutable成员变量。另外,对于指针类型成员变量,指针指向的内容可以修改,但指针本身不能修改。不过需要注意的是,通过指针修改内容可能在设计上破坏const的正确性,应该谨慎处理。 可能用户的实际需求是,他们在写一个类的时候,某个成员需要在const函数中被修改,这时候应该指导他们使用mutable,而不是尝试其他危险的方法。或者他们可能遇到了编译错误,想知道为什么const函数里不能修改某个变量,这时候需要解释const的规则和mutable的作用。 还要考虑用户是否了解const成员函数的基本用法,是否需要进一步解释this指针的变化?比如,在普通成员函数中,this是T*,而const成员函数中是const T*,所以通过this访问的成员都被视为const,除非有mutable。 有没有例外的情况或者编译器差异?一般来说,所有C++标准都遵循这个规则,不同编译器不会有差异。但用户可能在某些旧版本或特定环境下有不同行为吗?应该不太可能,所以主要围绕标准来回答。 最后,确保回答清晰,结构合理,先结论,再详细解释,举例子说明mutable和指针的情况,并强调不要用const_cast来绕过,这样用户能明白正确的做法和潜在的问题。在</think>C++中,**`const`成员函数不能修改类的非`mutable`成员变量**,但存在一些例外情况。以下是详细说明: --- ### 核心规则 1. **`const`成员函数的本质** 在`const`成员函数中,`this`指针的类型是`const T*`,即通过`this`访问的成员变量被视为`const`,因此**不可直接修改非`mutable`成员变量**。 2. **`mutable`关键字的作用** 若成员变量被声明为`mutable`,则即使在`const`成员函数中,该变量也可以被修改。 **用途**:适用于需要记录内部状态(如缓存、调试计数器)但对外表现为“逻辑不变”的场景。 ```cpp class Example { private: mutable int cache; // 可被const函数修改 int value; public: int getValue() const { cache++; // 合法:mutable变量可修改 // value++; // 非法:非mutable变量不可修改 return value; } }; ``` 3. **指针/引用成员的间接修改** - 若成员变量是指针或引用,`const`成员函数不能修改指针本身(如指向另一个地址),但**可以修改指针指向的内容**。 - 这种行为可能导致逻辑上的“状态变化”,需谨慎设计。 ```cpp class Data { private: int* ptr; public: void modifyContent() const { *ptr = 42; // 合法:修改指针指向的内容 // ptr = nullptr; // 非法:修改指针本身(非mutable) } }; ``` --- ### 禁止的绕过手段 - **`const_cast`的滥用** 强制移除`this`的`const`属性并修改成员变量是**未定义行为**(UB),必须避免: ```cpp void badIdea() const { const_cast<Example*>(this)->value = 42; // UB!切勿使用! } ``` --- ### 总结表 | 成员变量类型 | 在`const`成员函数中是否可修改 | |-----------------------|-------------------------------| | 普通成员(非`mutable`)| ❌ 不可修改 | | `mutable`成员 | ✅ 可修改 | | 指针指向的内容 | ✅ 可修改(不改变指针本身) | | 引用指向的内容 | ✅ 可修改 | --- ### 设计建议 - 使用`const`成员函数表明该函数不会改变对象的**逻辑状态**。 - 若需在`const`函数中修改成员变量(如缓存优化),使用`mutable`明确声明意图。 - 避免通过指针/引用间接修改内容破坏`const`语义,除非设计上明确允许。 通过合理使用`const`和`mutable`,可以在保证接口安全性的同时,灵活处理内部实现细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值