【问题标题】:C++ static initialization of stateless class无状态类的C++静态初始化
【发布时间】:2011-08-26 19:23:54
【问题描述】:

假设我有一个 T 类

  1. T 没有虚函数。
  2. T 实例没有状态。
  3. T 有自己的静态成员实例。
  4. T 本身没有其他状态。

C++ 静态初始化失败会毁掉我的程序吗?我不这么认为,因为即使其中一个静态实例在使用前没有被初始化,这也不重要,因为 T 对象是无状态的。

我有兴趣为类似枚举的类这样做:


// Switch.h

class Switch {
public:
    static Switch const ON;
    static Switch const OFF;
    bool operator== (Switch const &s) const;
    bool operator!= (Switch const &s) const;
private:
    Switch () {}
    Switch (Switch const &); // no implementation
    Switch & operator= (Switch const &); // no implementation
};

// Switch.cpp

Switch const Switch::ON;
Switch const Switch::OFF;

bool Switch::operator== (Switch const &s) const {
    return this == &s;
}

bool Switch::operator!= (Switch const &s) const {
    return this != &s;
}

【问题讨论】:

  • 很好的问题和一个有趣的想法!
  • 通过一个简单的枚举(没有额外的状态),这给了你什么?
  • 请发布一个您实际打算如何使用 Switch 类的示例。
  • 类声明在标题中,运算符和成员定义在某个 cpp 文件中,对吗?否则,这个问题是关于单一定义规则的,而不是关于静态初始化顺序的惨败。请说明您的代码示例是否是两个单独的文件。
  • 哎呀,对不起。这确实应该在两个单独的文件中。

标签: c++ static initialization stateless


【解决方案1】:

要回答您问题的第一部分,如果 T 有一个具有副作用的构造函数,那么您实际上可能会被静态初始化惨败所烧毁。

【讨论】:

    【解决方案2】:

    我感兴趣的是,您从包装在命名空间或类中的枚举中看到了哪些优势:

    namespace Switch {
       enum Switch {
          ON,
          OFF
       };
    }
    

    在大多数情况下使用起来会更简单(在您的实现中,您需要用户使用引用或指针,因为对象是不可复制的),它需要更少的代码(无需禁用构造函数,并创建运营商)...

    事实上,在即将发布的标准中,您几乎可以免费获得,甚至无需使用命名空间:

    enum Switch {
       ON,
       OFF
    };
    // bad, it allows this (as in the current standard):
    Switch s = ON;
    // good, it does also allow explicit qualification:
    Switch s = Switch::ON;
    

    【讨论】:

    • 我从来没有考虑过这个。虽然是魔鬼的拥护者,但我提出的类变体不允许隐式转换为整数。你也不能重新打开一个类,但这可以通过包装一个类而不是我猜的命名空间来解决。
    【解决方案3】:

    您真的打算使用指针值来比较“状态”吗?我同意@Drew,这是一个有趣的想法。不过,如果我们假设这是一个仅包含标头的实现,我不确定它是否能得到标准的保证。

    考虑当多个编译对象包含 Switch::ONSwitch::OFF 的相同定义时会发生什么。由于这些是变量,而不是函数,链接器必须在它们之间任意决定。

    当您运行测试时,流行的编译器会说什么:gcc 3、gcc 4、microsoft C++ 2005、2008 和 2010,以及 Edison Design Groups 的编译器之一,例如 http://www.comeaucomputing.com/

    所述测试将包括:

    // Switch.h
    class Switch {
    public:
        static Switch const ON;
        static Switch const OFF;
        bool operator== (Switch const &s) const;
        bool operator!= (Switch const &s) const;
    private:
        Switch () {}
        Switch (Switch const &); // no implementation
        Switch & operator= (Switch const &); // no implementation
    };
    
    Switch const Switch::ON;
    Switch const Switch::OFF;
    
    bool Switch::operator== (Switch const &s) const {
        return this == &s;
    }
    
    bool Switch::operator!= (Switch const &s) const {
        return this != &s;
    }
    

    // main.cpp
    #include "Switch.h"
    
    extern int another_test();
    
    int main(int argc, char*argv[])
    {
      another_test();
      const Switch& current_state = Switch::ON;
      const Switch& another_state = Switch::OFF;
      if (current_state == another_state) {
        return 1;
      } else if (current_state != another_state) {
        return 2;
      }
      return another_test();
    }
    

    // another_test.cpp
    #include "Switch.h"
    
    int another_test()
    {
      const Switch& current_state = Switch::ON;
      const Switch& another_state = Switch::OFF;
      if (current_state == another_state) {
        return 4;
      } else if (current_state != another_state) {
        return 5;
      }
      return 6;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-14
      • 2012-05-04
      • 2015-05-18
      • 2021-12-31
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      相关资源
      最近更新 更多