【问题标题】:Suppress messages printing from a const method禁止从 const 方法打印消息
【发布时间】:2013-11-12 12:22:55
【问题描述】:

我有一个类,其方法对某些变量执行一些检查并返回一个值,并最终打印一条警告消息。由于该方法不会更改任何类变量,因此我将其定义为 const。但是,为了避免淹没输出,我想在几次(或一次)打印后抑制警告打印。我一直无法找到保持方法 const 的解决方案,这可能吗(容易)?

【问题讨论】:

  • 您可以在函数中将本地计数器定义为静态变量。

标签: c++ methods constants


【解决方案1】:

使用mutable 计数器怎么样?我认为,应该可以接受,因为它不是对象的状态,而是内部的逻辑状态。

类似的东西

class Printer
{
public:
   Printer() : counter(0) {}
   void output() const
   {
      if (counter++ < max_warnings)
      {
         std::cout << "Something special" << std::endl;
      }
   }
private:
   static const size_t max_warnings = 5;
   mutable size_t counter;
};

Live example

由于有很多关于多线程的cmets,例如原子计数器

class Printer
{
public:
   Printer() : counter(0) {}
   void output() const
   {
      if (counter++ < max_warnings)
      {
         std::cout << "Something special" << std::endl;
      }
   }
private:
   static const size_t max_warnings = 5;
   mutable std::atomic<size_t> counter;
};

【讨论】:

  • +1 但是您应该确保不会遇到多线程问题。如果一个方法标记为const,用户通常希望它是 MT 安全的,因此您可能需要考虑使用原子计数器。
  • @DanielFrey 你是对的,但我认为,这个例子是多余的。
  • @DanielFrey 作为一个错误抑制器我可以承认一个小的竞争条件,但当然在更微妙的情况下也应该添加原子性。
  • FWIW,那些“用户”包括标准库。因此,如果此函数是容器或算法使用的某些操作(或者如果它是从任何此类const 操作中调用的),那么它必须在 C++11 中是线程安全的。然而,IIRC 标准中的措辞并没有明确说明这一点,而是说库的 const 操作是线程安全的。如果库在其const 操作中作用的对象不是,则此保证失败。 Herb Sutter 对这个领域非常感兴趣,IIRC 他认为标准应该只要求 const 始终表示“线程安全”。
  • 哦,“承认小的竞争条件”原则上总是有风险的,因为具有数据竞争的程序具有未定义的行为。尽管您可能会猜测(基于您对编译器和体系结构的了解)它会打印或不打印消息而没有任何令人不快的副作用,但标准中没有关于它可能出错的严重程度的限制。我还应该澄清一下,我在这里谈论的那种线程安全是并发/未排序的读取操作不会导致数据竞争——如果混合读取和写入是可以的(也就是说,const 操作与非-const) 不安全。
【解决方案2】:

你可以(坚持 ForEveR 中的 counter 示例)

  • 通过const_cast&lt;int&gt;(counter) 投射const
  • 使用不在此对象中的变量作为计数器

解决方案将取决于您的实际问题,您会在问题中添加代码 sn-p 吗?

【讨论】:

  • 我会通过设计避免 const_cast 并且计数器应该留在对象中,因为任何实例都应该有其特定的计数器。我认为 mutable 非常适合这种情况。有关代码 sn-p,请参阅 ForEveR 的答案,他说得对。
  • @DarioP:我明白了,这就是我要求提供代码 sn-p 的原因 :) 但问题标题对此保持开放,因此我的建议可能是其他人的选择。在我看来,suppress messages 这个词就像你在与编译器警告作斗争......
  • ...所以我对您的问题进行了编辑,这可能尚未获得批准。
  • ...这是rejected ;) 也许你想澄清一下...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-29
  • 2022-01-11
  • 1970-01-01
  • 2012-09-23
  • 2021-02-03
  • 1970-01-01
相关资源
最近更新 更多