常量成员函数可以修改数据成员

const member function can modify data member

本文关键字:修改 数据成员 成员 函数 常量      更新时间:2023-10-16

问题:为什么常量成员函数有时可以修改数据成员,有时不能?

解释:下面的代码是我工作基线中工作代码的摘录。

我有一个计算器类,它拥有一个名为"theLayout"的数据成员(下面定义的标头和实现)。计算器类有一个名为"Parms()"的常量成员函数,它返回一个智能指针,指向布局拥有的Parms对象(通过调用自己的Parms()函数)。

计算器类有一个名为 calculateStart() 的 const 成员函数,它设置(即修改)在计算器类中调用 Parms() 函数返回的引用。

这似乎与 const 对我来说的含义相矛盾。如果 const 成员函数无法修改 this 指针,那么为什么它可以在它拥有的一个数据成员 (theLayout) 上设置值?这难道不是"修改"计算器实例的 this 指针,从而与 const 成员函数的含义相矛盾吗?这是否有效,因为布局是一个指针?

计算器类

//Header
class Calculator
{
public:
   Calculator();
   //ParmsPtr is refcounted smart pointer
   const ParmsPtr& parms() const {return theLayout->parms();} 
protected:
   void calculateStart() const; //Why does this work?
   //It seems more intuitive that this should be declared as:
   void calculateStart() //with no const modifier.
   Layout&  theLayout;
}
//Implementation
void Calculator::calculateStart() const
{
   parms()->setStart(1);
}

布局类

//Header
class Layout : public RefCountedObject
{
public:
   Layout();
   //ParmsPtr is refcounted smart pointer 
   inline const ParmsPtr& parms() const;
private:
   ParmsPtr theParms;
}
//Implementation
inline const ParmsPtr& Layout::parms() const
{
   if (!theParms)
   {
      Layout* nonConstThis = const_cast<Layout*>(this);
      ParmsPtr parms = new Parms();
      nonConstThis->setParms(parms);
   }
   return theParms;
}

计算器类有一个名为 calculateStart() 的 const 成员函数,它设置(即修改)在计算器类中调用 Parms() 函数返回的引用。

是的,calculateStart()确实修改了计算器对象,考虑到其定义中的最终 const 限定符,这是出乎意料的。

为什么?看看inline const ParmsPtr& Layout::parms() const的定义;最终const告诉编译器该函数不会修改Layout对象,尽管它实际上会修改。如何?通过恶作剧地将对象const_cast到非常量对象;这就是恒常性被打破的地方,这就是为什么setParms()可以被召唤。

这是一种不好的做法,尽管可能有一些原因这样做。在这种情况下,const_cast可以达到此目的。

关键问题是,通过将 start() 声明为 const 究竟是什么? 答案是引用,而不是引用的值

在您的示例中,在 start() 方法中,编译器将数据成员视为具有 Layout const&,这与 const Layout& 不同。 同样的事情也适用于指针。 如果数据成员是指针类型,编译器会将该类型视为布局 const*。