【问题标题】:Giving an error when a function is not called before之前未调用函数时出错
【发布时间】:2018-05-09 22:02:41
【问题描述】:

我正在尝试在基于 C++ 的应用程序中管理初始化函数。我想:

  • 确保init_some_hw_peripherals()(见下文)只运行一次,即使init() 被多次调用。

  • 如果未从对象调用另一个函数 init_some_hw_peripherals()previously,则阻止执行函数 doPerform()

我想到了以下解决方案,但它不起作用(如果未初始化,我不会收到任何错误消息)。我知道为什么它不起作用,而且非常有意义。但我想使用这些类型的定义来实现我提到的。我希望这些信息对您有所帮助。

如果您能帮助我处理这种情况并给我一些指导,我将不胜感激。

提前致谢。

初始化

void myClass::init(void)
{
#ifndef MY_INIT_
#define MY_INIT_
      init_some_hw_peripherals();
#endif
}

应用程序

void myClass::perform (void)
{
#ifndef MY_INIT_
#error "You havent initialized. Use myClass::init()"
#else
      doPerform();
#endif
}

编辑:对我来说使用私有变量的问题是我有几个类可以调用 init 函数。所以我不想让它成为一个私有变量。这就是为什么我坚持这种解决方案,因为我知道它最初不会起作用。

【问题讨论】:

  • 您的#ifdef 将无助于防止多次执行 init_some_hw_peripherals()。在程序编译之前而不是在运行时进行评估。
  • #defines 和 #ifndefs 确实知道“函数”的概念。为什么private 变量不能用于此目的?
  • 如果您能帮助我处理这种情况并给我一些指导,我将不胜感激。使用布尔变量。在构造函数中将其设置为 false。当调用 init_some_hw_peripherals() 时,将其设置为 true。执行 perform() 时检查是否为真

标签: c++ initialization preprocessor assertions


【解决方案1】:

通常,init-like 函数的存在表明缺少适当的构造函数。给定的要求显然导致了两个具有专用构造函数的类:

class hwPeripherals
{
      private: static ::std::atomic_bool s_construction_attempted;

      // instead of init_some_hw_peripherals
      public: hwPeripherals(void)
      {
          // Check that no attempts of hwPeripherals construction happened yet.
          if(s_construction_attempted.exchange(true))
          {
               // Throw an exception.
          }
          // Initialization... Throw an exception if fails.
      }
};

class myClass
{
     private: myClass(void) = delete;

     // instead of init
     public: explicit myClass(hwPeripherals & peripherals)
     {
          // Initialization... Throw an exception if fails.
     }

     public: void perform(void);
};

这种调用perform用户的方式需要先实例化myClass,然后这个用户需要实例化hwPeripherals

hwPeripherals peripherals{};
myClass obj{peripherals};
obj.perform();

【讨论】:

    【解决方案2】:

    你可以使用私有成员来告诉你初始化是否完成:

    class myClass {
    public:
        myClass() : isInit(false) {}
        ...
    private:
        bool isInit;
    };
    
    void myClass::init(void)
    {
        if (!init) {
          init_some_hw_peripherals();
          init = true;
        }
    }
    
    void myClass::perform (void)
    {
        if (!init) {
            cout << "You havent initialized. Use myClass::init()";
        } else {
          doPerform();
        }
    }
    

    【讨论】:

    • 这种方法对我来说的问题是我有几个类可以调用 init 函数。所以我不想让它成为一个私有变量。这就是为什么我坚持这种解决方案,因为我知道它最初不会起作用。
    • @mozcelikors 无论如何调用init 函数,这仍然有效。
    • 嗯,你是对的。这当然是一种解决方案,因为 init 是一个类对象。如果其他人有更多想法,我会等待其他人。最终,我会选择最佳答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-07
    • 1970-01-01
    • 2012-07-22
    相关资源
    最近更新 更多