2011-08-06 89 views
7

我有一个叫头filepaths.h它定义了一些静态变量:为什么静态变量需要在C++中声明两次

#ifndef FILEPATHS_H 
#define FILEPATHS_H 

class FilePaths { 

public: 

    static QString dataFolder(); 
    static QString profileFolder(); 

private: 

    static QString dataFolder_; 
    static QString profileFolder_; 

}; 

} 
#endif // FILEPATHS_H 

而且我有一个相关的filepaths.cpp这一开始是这样的:

#include "FilePaths.h" 

QString FilePaths::dataFolder() { 
    return dataFolder_; 
} 

QString FilePaths::profileFolder() { 
    return profileFolder_; 
} 

但是没有工作 - 我对所有的静态变量得到了一个“未解决的符号错误”连接错误。所以我以这种方式添加这些变量到C++文件:

#include "FilePaths.h" 

QString FilePaths::dataFolder_ = ""; 
QString FilePaths::profileFolder_ = ""; 

QString FilePaths::dataFolder() { 
    return dataFolder_; 
} 

QString FilePaths::profileFolder() { 
    return profileFolder_; 
} 

而这个工作,但是我不明白为什么。

为什么这些静态变量需要定义两次?或者,也许我没有定义他们,但初始化他们?但仍然为什么需要这样做?还是应该以不同的方式写我的课程?

回答

8

一个是定义,另一个是声明。不同之处在于声明可以多次出现,对于不在类中的变量,可能永远不会出现,而定义只能出现一次。

需要单独声明和定义的原因是古老的历史,它基本上不必是那种方式,但它是这样的,以便C++与C兼容,C被设计为在20世纪70年代被编辑。

+3

我不认为这是古老的。声明声称“存在某个名为X的变量/类/函数”,而定义说“X驻留在这里,编译器请为它分配存储空间”。分离声明和定义的能力是允许多种翻译单元采用静态类型的语言,而编译器不需要过度“聪明”并猜测自己的意图。 – vsekhar

+0

这并不是很陈旧,因为这两个标准(甚至现在,C99/C++ 11)在实际的链接器进程上都非常模糊,并且某个cpp文件中的定义将导致生成的目标文件中有一个定义,如果这并非如此,链接器在将所有代码链接在一起时不会找到唯一的引用。 – rubenvb

+0

vsekhar,@rubenvb:我会注意到,对于模板代码,我们获得了函数和静态属性的多个定义(在对象文件中),但链接器管理它们是正确的。 –

2

http://weblogs.asp.net/whaggard/archive/2004/11/05/252685.aspx

你需要声明它的类之外,因为否则编译器不知道哪个翻译单元(因此目标文件)的成员应该去。

因为,就像DeadMG说的那样,你可以多次声明一个变量,但只定义它一次。我认为它就像函数原型一样:你可以拥有尽可能多的函数原型,但是只有一个可以与一个物体一起去实际定义函数。

0

你不要声明它们两次,声明发生在类头和定义 - 变量实际存在并将分配一些内存的位置 - 位于.cpp部分。

但是,与常见实例变量的区别在于,对于您创建的任何实例,静态部分仅对每个类有一次。

0

这是因为,当你声明一个类的时候,你就是为这个类的特定实例声明一个结构,但是在类中有静态变量的情况下,它们是可以在任何对象之前初始化的结构的类被创建。 SEE当我们在内存中声明一个类时没有保留空间,但是当我们声明类的对象时,空间是保留的。类的成员可以被初始化,如 int a = 2;但是这可以像'static int a = 2;'那样完成有可能 在类声明的预留空间为他们有第二个声明,&必须让它知道它

相关问题