如何在c ++中避免使用非原始静态类变量的问题?

时间:2011-02-08 15:01:11

标签: c++

我已经阅读了很多关于c ++中静态类变量初始化的内容,而谷歌编码标准说只创建普通旧数据的静态(即原语和指针),我在网上看到了很多例子。作者违反该指南的书籍。

我还读过,只要你将静态保存在一个编译单元中,就不太可能遇到未定义的初始化问题。

好的...所以说...我想要一些专家意见,我是否会遇到一些问题,看起来像......

//header file snippet
struct TheStruct {
    string theString;
    string theString2;
    float theFloat;
};

class TheClass {
public:
    static const TheStruct Dude;
    static const TheStruct Blah;
    static const TheStruct TheStructArray[];

    TheClass();
    virtual ~TheClass();
    TheStruct getCurrent();
private:
    TheStruct current;
}

//impl file snippet
const TheStruct TheClass::Dude = { "Dude", "Dude", 0 };
const TheStruct TheClass::Blah = { "Blah", "Blah", 0 };
const TheStruct TheClass::TheStructArray[] = {TheClass::Dude, TheClass::Blah};

TheClass::TheClass() : current(TheClass::Dude) {}
TheClass::~TheClass() {}
TheStruct TheClass::getCurrent() {return current;}

我认为getCurrent()方法没问题。静态const DudeBlah包含在静态数组TheStructArray中,以便将来使用。但是,我猜我仍然会遇到阵列的问题,如果它被其他一些类使用的话?例如,GUI可以使用该数组来提供可供选择的有效选项。

我来自Java背景,因此我经常使用private static final来定义一些有效的“状态”......

谢谢!

2 个答案:

答案 0 :(得分:3)

//impl file snippet
const TheStruct TheClass::Dude = { "Dude", "Dude", 0 };
const TheStruct TheClass::Blah = { "Blah", "Blah", 0 };
const TheStruct TheClass::TheStructArray[] = {TheClass::Dude, TheClass::Blah};

只要这三行按顺序编写,代码就没有问题,因为它们按照上述顺序初始化,因此您不会遇到 static initialization order fiasco。否则,您应该通过this link了解您可能遇到的问题以及您必须提供的solution

答案 1 :(得分:1)

可能可能会出现问题

TheClass::TheClass() : current(TheClass::Dude) {}

IF并且仅当您在代码中的不同cpp中声明了静态或全局TheClass时。例如:

// somewhereelse.h
#include "TheClass.h"

class OtherClass {
  static TheClass myTheClass;
  }

// somewhereelse.cpp
TheClass OtherClass::myTheClass;

初始化“OtherClass :: myTheClass”对象(调用构造函数并访问TheClass :: Dude)可能会在TheClass :: Dude初始化其值之前发生。因此,您可能会在OtherClass :: myTheClass的构造函数中获得随机垃圾(或更糟糕的崩溃)。

这可以通过使用不同复杂度的c ++单例模式(取决于您的要求)来避免这种情况。

struct TheStruct {
  string theString;
  string theString2;
  float theFloat;
};

class TheClass {
public:
    static const TheStruct &Dude();
    static const TheStruct &Blah();
    static const TheStruct *TheStructArray();

    TheClass();
    virtual ~TheClass();
    TheStruct getCurrent();
private:
    TheStruct current;
};

//impl file snippet
const TheStruct &TheClass::Dude() {
  static TheStruct DudeStruct = { "Dude", "Dude", 0 };
  return DudeStruct;
  }

const TheStruct &TheClass::Blah() {
  static TheStruct BlahStruct = { "Blah", "Blah", 0 };
  return BlahStruct;
  }

const TheStruct *TheClass::TheStructArray() {
  static TheStruct singletonStructArray[] = {TheClass::Dude(), TheClass::Blah()};
  return singletonStructArray;
  }

TheClass::TheClass() : current(TheClass::Dude()) {}
TheClass::~TheClass() {}
TheStruct TheClass::getCurrent() {return current;}

现在,无论在其他地方如何使用TheClass,初始化都不会被定义。如果OtherClass有一个静态的TheClass对象,即使它在其他任何东西之前被初始化,DudeStruct也会及时初始化为“current”的复制构造函数。