2011-02-08 45 views
2

我已经读了很多有关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()方法没问题。静态常量DudeBlah包装在静态数组TheStructArray中,道路上的东西将使用。但是,我猜如果它被其他类使用,我仍然会遇到数组的问题。例如,GUI可以使用该阵列来呈现有效选项以供选择。

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

谢谢!

+3

不要将Google编码标准视为良好编程实践的指南。 – 2011-02-08 15:17:49

回答

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

+2

+1:简洁明了的答案! – 2011-02-08 15:42:37

1

其可能你可能

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

IF的问题,只有当你有一个静态的或全局theClass描述在代码中的不同CPP声明。例如:

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

class OtherClass { 
    static TheClass myTheClass; 
    } 

// somewhereelse.cpp 
TheClass OtherClass::myTheClass; 

初始化“OtherClass :: myTheClass”对象(调用构造函数和访问theClass描述::多德)theClass描述之前,可能会出现::哥们有其值初始化。因此,你可能会在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”的拷贝构造函数。

+1

您的最后一个选项不是线程安全的! – Nim 2011-02-08 16:17:05

相关问题