C++无状态类的静态初始化

C++ static initialization of stateless class

本文关键字:静态 初始化 状态 C++      更新时间:2023-10-16

>假设我有一个类 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;
}

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

我对你从命名空间或类中包装的枚举中看到的优势感兴趣:

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;

你真的打算使用指针值来比较"状态"吗? 我同意@Drew,这是一个有趣的想法。 但是,如果我们假设这是一个仅标头的实现,我不确定标准是否保证它能够正常工作。

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

当你运行测试时,流行的编译器说了什么:gcc 3,gcc 4,Microsoft C++ 2005,2008和2010,以及爱迪生设计小组的编译器之一,如 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;
}