【问题标题】:Why do static variables need to be declared twice in C++为什么静态变量需要在 C++ 中声明两次
【发布时间】:2011-10-21 12:22:24
【问题描述】:

我有一个名为 filepaths.h 的头文件,它定义了许多静态变量:

#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_;
}

这行得通,但我不明白为什么。

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

【问题讨论】:

    标签: c++ class variables static


    【解决方案1】:

    这是因为,当你声明一个类时,你是在为该类的特定实例声明一个结构,但是对于一个类中的静态变量,它们是可以在任何对象之前初始化的类被创建。 看到我们在内存中声明一个类时没有保留空间,但是当我们声明类的对象时保留了空间。类的NO成员可以像这样发起 诠释一个= 2;但这可以像'static int a=2;'是可能的 在类声明中为他们保留第二个声明的空间,&必须意识到这一点

    【讨论】:

      【解决方案2】:

      您不必两次声明它们,声明发生在类头中,而定义(变量实际存在并分配一些内存的点)位于 .cpp 部分。

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

      【讨论】:

        【解决方案3】:

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

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

        因为就像 DeadMG 所说,你可以多次声明一个变量,但只能定义一次。我认为它就像函数原型:您可以拥有任意数量的原型,但只有一个可以使用主体并实际定义函数。

        【讨论】:

          【解决方案4】:

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

          需要单独的声明和定义的原因是过时的历史,它基本上根本不需要那样,但它是这样的,以便 C++ 与 C 兼容,它被设计为编译于 1970 年代。

          【讨论】:

          • 我不认为这是过时的。声明说“某处存在一个名为 X 的变量/类/函数”,而定义说“X 驻留在此处,编译器请为其分配存储空间”。分离声明和定义的能力允许在静态类型语言中使用多个翻译单元,而编译器不需要变得过于“聪明”并猜测你的意图。
          • 这并不是真正的过时,因为这两个标准(即使是现在,C99/C++11)对实际的链接器过程都非常模糊,并且某个 cpp 文件中的定义将导致一个定义生成的目标文件,如果不是这种情况,则链接器在将所有代码链接在一起时将找不到唯一引用。
          • vsekhar, @rubenvb:我会注意到,对于模板代码,我们得到了函数和静态属性的多个定义(在目标文件中),但链接器可以正确管理它们。
          • “陈旧”部分正是构建模型,其中必须告知程序的某些部分存在于程序的其他部分中的内容。例如,Java 编译器可以查找它需要知道的所有内容,因此可以根据程序员的需要使用接口,而不是编译器的需要。 C的模型有一些优点。他们中的一些人坚持到了今天,尽管他们是否值得付出代价是值得怀疑的。但许多最初的优势与过时的编译时资源限制有关,并且不会持续到今天。
          • 这很古老,因为程序员根本需要处理它。几乎所有其他编译语言都不需要这种系统,并且必须一遍又一遍地重复解析相同的声明非常慢。
          猜你喜欢
          • 2016-11-22
          • 2013-08-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-11-20
          • 1970-01-01
          相关资源
          最近更新 更多