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

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

3
好问题,有趣的想法! - Drew Hall
这与简单的枚举(没有额外状态)相比,给你什么? - Nim
请提供一个使用Switch类的实际示例。 - user2100815
类声明在头文件中,运算符和成员定义在某个cpp文件中,对吗?否则,这个问题是关于单一定义规则,而不是静态初始化顺序混乱的问题。请说明您的代码示例是否为两个独立文件。 - Rob Kennedy
抱歉,这确实应该分成两个不同的文件。 - Thomas Eding
3个回答

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;

1
我从未考虑过这一点。虽然作为一个恶魔的代言人,我提出的类变体不允许隐式转换为整数。此外,您无法重新打开一个类,但我想通过将其包装在类而不是命名空间中来解决这个问题。 - Thomas Eding

2
回答你问题的第一部分,如果 T 有一个具有副作用的构造函数,那么你实际上可能会遭遇静态初始化灾难。

0

你真的打算使用指针值来比较“状态”吗?我同意@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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接