【问题标题】:Member function called only on initialization of first instance of a class (C++)仅在类的第一个实例初始化时调用的成员函数 (C++)
【发布时间】:2013-06-08 03:56:23
【问题描述】:

我有一个基类的成员函数,我只想在初始化该类的第一个实例(无论是基类的直接实例还是继承的类)时调用 [一次]。基本上,我想避免不必要的函数调用。

【问题讨论】:

  • 看看std::call_once
  • 如果你不想/不能使用 c++11 或者你认为 juanchopanza 提出的解决方案过头了,你可以使用一个静态 bool 标志来指示函数已经运行并且不要再次运行它。
  • 我觉得以上两个cmets应该结合起来才能得到答案。:-)

标签: c++ inheritance member-functions


【解决方案1】:

仅在第一次发生某些事情时才完成的事情是在第一次执行周围函数期间初始化函数局部静态。那么你该怎么做呢:

class X {
  static int firstInitFunc();

public:
  X() {
    static int onFirstCtorCall = firstInitFunc();
  }
};

现在第一次创建XonFirstCtorCall 将被初始化(线程安全),调用该函数。 X 的任何后续创建都不会再次调用该函数。

如果您在X 上有多个构造函数,您仍然只需要一次调用该函数。您可以通过使用静态变量委托给构造函数或使用另一个静态函数来实现:

C++11:

class X {
  static int firstInitFunc();

public:
  X() {
    static auto onFirstCtorCall = firstInitFunc();
  }
  X(int) : X() // delegate to X()
  { /* ... */ }
};

C++03:

class X {
  static int firstInitFunc();

  static void callFirstInit() {
    static int onFirstCtorCall = firstInitFunc();
  }

public:
  X() {
    callFirstInit();
  }
  X(int) {
    callFirstInit();
  }
};       

更新:我会参考 juanchopanza 的评论并提供一个使用 std::call_once 的示例:

C++11 使用 call_once

class X {
  static void firstInitFunc(); //see note to return types
  static std::once_flag firstInitFlag;

public:
  X() {
    std::call_once(firstInitFlag, firstInitFunc);
  }
  X(int) { 
    std::call_once(firstInitFlag, firstInitFunc);
  }
};

返回类型的注意事项:虽然在用于函数调用的函数局部静态初始化的情况下,该函数必须返回一个值,而静态将被初始化。相比之下,std::call_once 函数可能没有返回类型,因为任何返回值都不会被计算。

【讨论】:

  • +1 线程安全由 [stmt.dcl]/4 保证;尽管std::run_once 可能更惯用。
  • @DyP 添加了std::run_once 解决方案
  • @ArneMertz +1:-) 很好的答案。
【解决方案2】:

简单的解决方案:

class C
{
private:
    static bool runOnce;

public:
    C()
    {
        if (!C::runOnce)
        { 
            C::runOnce = true;
            RunSth();
        }
    }
};

bool C::runOnce = false;

【讨论】:

  • 它甚至不必是类的静态数据成员;它也可以是一个局部静态变量。
  • 也许有更清洁的标准方法吗?某种方法可以在没有每个实例的条件检查和添加的变量的情况下做到这一点?我知道我对一个字节有点挑剔......但我想学习如何编写干净的代码。
  • @PhillipWeber “对一个字节有点挑剔” 干净的代码。尽管使用 C++11 的 std::run_once,但它也需要一些存储空间。
  • @PhillipWeber 查看 Arne 的回答 :)
  • @PhillipWeber 重点是,有时为了保持代码干净,您必须使用额外的变量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多