问题:为什么const成员函数有时会修改数据成员,有时候不能修改数据成员?
解释:下面的代码摘自我工作基线中的工作代码。
我有一个Calculator类,它拥有一个名为“theLayout”的数据成员(下面定义的Header和Implementation)。计算器类有一个名为“Parms()”的const成员函数,它返回一个智能指针,该指针指向theLayout拥有的Parms对象(通过调用它自己的Parms()函数)。
计算器类有一个名为calculateStart()的const成员函数,它设置(即修改)从Calculator类中调用Parms()函数返回的引用。
这似乎与const的含义相矛盾。如果const成员函数无法修改this指针,那么为什么它可以在它拥有的其中一个数据成员(theLayout)上设置一个值?这不是“修改”Calculator实例的this指针,因此与const成员函数的含义相矛盾吗?这是否有效,因为theLayout是一个指针?
计算器类
//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;
}
答案 0 :(得分:1)
计算器类有一个名为calculateStart()的const成员函数,它设置(即修改)从Calculator类中调用Parms()函数返回的引用。
是的,st.sorted( Map.Entry.<K, V>comparingByValue().reversed() )
.forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
会修改计算器对象,考虑到其定义中的最终const限定符,这是意外的。
为什么?看看calculateStart()
的定义;最后的inline const ParmsPtr& Layout::parms() const
告诉编译器该函数不会修改const
对象,尽管它实际上是这样。怎么样 ?通过错误地Layout
将对象转换为非const对象;这就是常量被打破的地方,这就是为什么可以调用const_cast
。
这是一种不好的做法,尽管可能有一些理由这样做。在这种情况下,setParms()
就是为了这个目的。
答案 1 :(得分:-2)
关键问题是,通过将start()声明为const,究竟是什么形成了const?答案是引用,而不是引用的值。
在您的示例中,在start()方法内,编译器将数据成员视为具有类型Layout const&amp;,这与const Layout&amp ;;不同。同样的事情适用于指针。如果您的数据成员是指针类型,编译器将看到类型为布局const *。