代码之家  ›  专栏  ›  技术社区  ›  Fanatic23

需要静态变量的类外定义吗?

c++
  •  2
  • Fanatic23  · 技术社区  · 14 年前

    我的问题是:为了确保K的地址是可用的,K的类外定义到底是什么?

    #include <iostream>
    using namespace std;
    
    class A { 
      public: 
      static const float k = 7.7;
    };
    
    //const float A::k; --> without this line compiler error
    
    int main()
    {
      cout << &A::k;
    }
    
    6 回复  |  直到 14 年前
        1
  •  1
  •   Billy ONeal IS4    14 年前

    其他的答案已经给出了如何修复它的方法——我将更深入地探讨原因。

    当你这样做的时候:

    #include <iostream>
    using namespace std;
    
    class A { 
      public: 
      static const float k = 7.7;
    };
    
    int main()
    {
      cout << A::k;
    }
    

    编译器可能实际上正在生成:

    #include <iostream>
    using namespace std;
    
    class A { 
      public: 
      static const float k = 7.7;
    };
    
    int main()
    {
      cout << 7.7;
    }
    

    这意味着这个翻译单元和 A::f --编译的代码没有引用 答:F 完全!

    但是,当你使用 &A::f ,强制编译器为 答:F . 因此翻译单位 依赖 答:F . 因为您没有定义它,所以会得到一个链接器错误,因为链接器找不到它的地址。为了地址的存在, 答:F 必须在一个中定义 只有一个 翻译单位。要选择它应该驻留的翻译单元,需要在那里定义它。

    不过,上面的类也有一个无效的代码问题——仅 静态常量积分 成员可以用您使用的语法初始化(在类体中放入k=7.7)。-- float 不是整型。

        2
  •  2
  •   Alex Martelli    14 年前

    类“definition”实际上只提供 A::k . 是的,我知道这很令人困惑,但我的想法是允许类定义在 .h (包括多个 .cpp 来源)不产生歧义:其中一个,而且只有一个 CPP 来源,必须提供 定义 相配 答:K 宣言 (后者是班级的一部分) A 定义 )

        3
  •  1
  •   Potatoswatter    14 年前

    听起来您好像在想为什么需要定义变量,即使您没有访问它。

    要打印地址,它需要有一个地址。要有地址,它必须存在。要存在,它需要有一个定义,而链接器需要在全局变量空间中为其分配一个位置。所以,没有中间地带。

    “在引擎盖下,”定义告诉链接器全局的初始值设定项是什么。(在这种情况下,初始值设定项位于 class 块。但这是不标准的。正式的方式是写作 const float A::k = 7.7; )不知道这一点,它就无法生成可执行文件。

    另外,除非编译器执行不可能详细的分析,否则它不能真正说明 operator << 不会以某种方式将该指针传递给其他函数或操作系统服务, 访问的值 k .

        4
  •  1
  •   liaK    14 年前

    如果你能定义像 static const float k = 7.7; 如你所愿 ,您将得到多个定义( 因为静态成员只定义一次 无论你在哪里,包括它。

    为了避免定义是单独存在于 cpp 文件。

    从C++标准文档SEC 9.4.1,

    静态数据成员是 不是部分 类的子对象。有 只有一份 静态数据成员的 共享 所有对象 班里的

    另外,9.4.2规定,

    静态数据成员在其类定义中的声明 不是定义 可能是不完整的类型 除简历合格无效外。静态数据成员的定义 将出现 在一个 名字空间作用域 围住 成员的类定义。

    希望它有帮助。

        5
  •  1
  •   Naveen    14 年前

    班里的那个是 宣言 变量的 k . 你需要 定义 它正好位于一个翻译单元中,以便正确链接您的程序。因此,该声明是必需的。

        6
  •  0
  •   mukeshkumar    14 年前

    静态变量可以被视为类的所有对象共享的数据,因此只应创建该变量的一个副本。有了这句话,谁应该承担为这个成员分配内存的责任呢?显然,它不能是对象的责任,因为可能存在多个对象,这将引发另一个挑战,即哪个对象应该为该成员分配内存。

    因此,通常compliler需要类外的、该成员的显式定义,因此行:

    const float A::k;

    这样可以确保类的所有对象都可以访问静态成员变量。这个变量的内存分配在全局可访问的内存上。