正确替代c ++中的"可变函数"

Tom*_*Tom 14 c++ mutable

在c ++中的类中包装算法时,我经常遇到const正确性的问题.我觉得我想要一个可变功能,虽然这是不允许的.任何人都可以建议我如何实现如下的类?

以下是我编写的代码.

  • 函数run()不应该是const函数,因为它会更改数据.
  • 函数get_result()应该是一个常量函数(就用户而言),因为它返回数据.

但是,如果用户在不调用run()的情况下请求结果,我希望get_result()函数运行算法.这打破了const的正确性,因为我有一个const函数调用非const函数.

class operate_on_data
{
  std::vector<double> m_data;  // the data to modify
  bool m_completed;  // check to see if the function run() has been called
public:
  operate_on_data(std::vector<double> data)
    : m_data(data), m_completed(false) {}  //initialise
  void run() //I don't want this function to be const  
  {
    //The algorithm goes here - it alters m_data.
    m_completed = true;  //the algorithm has been run
  }
  std::vector<double> get_result() const //I want this function to be const
  {
    /*The following breaks const correctness because 
      I am calling a non-const function from a const function
      - but this feels like the right thing to do ... */ 
    if (!m_completed) run();  //run the algorithm if it has not run already
    return m_data; //return
  }
};
Run Code Online (Sandbox Code Playgroud)

我曾经设法编译上述类的唯一方法是

  • make run()const,并使m_data和m_completed变为可变.这有效,但在概念上是错误的,因为run()明显改变了数据.
  • 使get_result()不是一个常量函数.这似乎也是错误的,因为用户希望这个函数是一个简单的返回,因此是常量.
  • 将run()函数放入get_result()const函数并使数据变量可变.

我的理解是mutable关键字是为第三个选项设计的,其中实现需要更改数据,但用户合理地期望简单的返回,因此const函数.

但是,我不想做最后一个选项,因为我希望用户能够准确选择何时更改数据.但是,他们有可能忘记调用run(),因此我想强制算法,如果他们在不调用run()的情况下请求结果.我觉得想要使run()变得可变 - 但我不被允许.

写这样一堂课的正确方法是什么?

Edw*_*nge 9

make run()const,并使m_data和m_completed变为可变.这有效,但在概念上是错误的,因为run()明显改变了数据.

事实并非如此.事实上,你班级中的变量已被改变,但你永远无法证明这一点.调用run()不会更改用户可以从类的接口检索的任何内容.如果您无法检索有关此类更改的任何信息,则无法证明该更改.这不仅是一个语义问题的更多,它直接讲的"可变"关键字的整点.

'mutable'关键字被误解了很多.

这就是说,虽然与最低限度给定的信息我有我可能会做上述方式,我不会推荐它.鉴于对问题的更大看法,几乎可以肯定有一种更好的方法.

我可能使用的另一种方法是你显然避免使用的方法:强制用户在使用get_data()之前调用run().说实话,这也是一个非常不理想的方法.也许更是如此.

编辑:

如果您决定使用可变方法,那么我建议进行一些更改.有一个名为'run()'的函数是const并且没有任何感兴趣的东西会让人感到困惑.这个函数当然应该是非常量的.因此,如果决定以这种方式做这件事,我会做的就是让run()调用一个const和private函数,它具有当前'run()'函数的行为,get_data也引用它( )在规定的条件下.

  • 是啊.我当然不会将我的决定建立在SO共识上.这种情况也不例外.这里的"正确"答案几乎肯定会杀死你的这个对象; 它没有做任何有趣的事情.我的帖子只是解释为什么你和其他人对const/mutable问题的分析存在缺陷. (3认同)

Kos*_*Kos 5

一些抽象的评论可以帮助你澄清事情:

  • const 方法是那些不修改对象的概念"状态"的方法,
  • const方法是那些做的.
  • 另外,mutable字段是每个对象的字段,但不被视为对象概念的一部分state(就像一些被懒惰和记住的缓存值).

问题可能operate_on_data不是一个定义明确的类.什么是类"operate_on_data"的对象?这个对象的"状态"是什么?什么不是?这听起来很尴尬(至少对我而言) - 对某些设计的尴尬描述可能表明反直觉的设计.

我的想法是你在一个奇怪的课堂上保持"操作"和"操作结果"的不同概念,这会导致混乱.

  • 一个"仿函数" - 我一直都理解它 - 是一个可以被调用来运行一个操作的对象如果"逻辑参数"作为functor实例的字段或作为`operator()的参数传递则无关紧要.但是一个仿函数不负责保持计算结果 - 至少我从来没有偶然发现它会有一个惯例,这是完全合理的."操作"是一回事,"操作结果"是另一回事. (2认同)