C++ 如果调用中断的函数,则成员函数仍为常量;康斯特内斯;?

C++ 如果调用中断的函数,则成员函数仍为常量;康斯特内斯;?,c++,constants,C++,Constants,我想知道,如果一个类调用了修改其数据成员的其他函数,它的成员函数是否应该是const。一个很好的例子是一个公共成员函数,它使用私有成员函数来完成最主要的工作 void Foo::Show() const { // Doesn't directly modify data members in this function ShowPig(); // One or all of these functions modify data members ShowCow(); Sh

我想知道,如果一个类调用了修改其数据成员的其他函数,它的成员函数是否应该是const。一个很好的例子是一个公共成员函数,它使用私有成员函数来完成最主要的工作

void Foo::Show() const { // Doesn't directly modify data members in this function
    ShowPig(); // One or all of these functions modify data members
    ShowCow();
    ShowBar();
}

也许不是最好的例子,但你明白了。

任何好的编译器都不允许这样做。您应该得到编译器错误。

编译器不允许您这样做。下面的例子

//MS VC 2008
class Foo
{
  int m_iBar;

  void ThisIsConstFunc() const
  {
    m_iBar = 9; //error C2166: l-value specifies const object
    ThisIsNonConst(); //error C2662: 'Foo::ThisIsNonConst' : cannot convert 'this' pointer from 'const Foo' to 'Foo &'
  }

  void ThisIsNonConst() 
  {
    m_iBar = 9;
  }
};

如果函数调用修改某些数据的函数,那么应该说函数本身修改数据。它只是碰巧是抽象的


因此,不,该函数不应该是常量。

C++提供了可变关键字,用于您实际希望允许这种情况的罕见情况。有时会发生这种情况,例如,如果函数不更改对象的逻辑状态,但可能修改对象的一个或多个成员


这些病例非常罕见。在绝大多数情况下,如果成员函数const或其调用的任何函数都不修改对象的状态,则应标记该成员函数const。

是的,如前所述,编译器不允许您这样做。当然,你可以这样做,但如果函数需要常量,通常这是一个坏主意。如果不需要常量,不要无缘无故地把它放在那里。const实际上没有什么好处,也没有很多潜在的严重问题,你只是偶尔被迫使用它。

const可以被丢弃。问题不在于常量方法是否可以/应该调用非常量方法,而在于如何解释你正在执行
const\u cast
(无论如何,尤其是出于这个目的)@Dribea你说得对,我终于100%理解了这个问题(以及公认的答案)在读了第五十遍之后。可变类的第一种情况是延迟求值。您可以使用一个函数执行一次昂贵的操作并缓存该值。缓存和保护变量(如果有)应该是可变的。这允许延迟求值类仍然将函数声明为常量,但仍然受益于lazy求值。我读过一次“如果一个方法不修改可感知的状态,那么它应该是常量,也就是说,如果在调用常量方法之前和之后,对象上的所有操作都将具有相同的效果”行中的一个定义。互斥体是可变关键字的第一个候选对象,然后还有其他类似于缓存结果的结果…有以下是关于可变的参数:"如果一个函数改变了一个类的状态,比如datamembers,但是没有改变它的行为,通过它的公共接口,它可能是常量,也可能不是常量?而被接受的答案是肯定的。它可能是常量,而且通常应该是常量。让用户指定另一个函数不执行重大更改是有价值的。例如,统计数据收集、数据库优化、触发某些GC机制、缓存优化等。为此,“可变”被发明出来,我发现它很有用。当我想延迟数据成员的初始化直到它们被访问时,我经常使用可变。这防止了许多应用程序中出现的巨大初始化延迟e方法被认为是常量,但它初始化其数据成员的一个实例除外。