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

C++中的静态const双

  •  10
  • Crystal  · 技术社区  · 15 年前

    这是使用静态常量变量的正确方法吗?在我的顶级班(形状)

    #ifndef SHAPE_H
    #define SHAPE_H
    
    class Shape
    {
    public:
    
        static const double pi;
    private:
        double originX;
        double originY;
    };
    
    const double Shape::pi = 3.14159265;
    
    #endif
    

    稍后在扩展形状的类中,我使用shape::pi。我收到一个链接器错误。我移动了常量双形::pi=3.14…然后编译到shape.cpp文件和我的程序。为什么会这样?谢谢。

    7 回复  |  直到 7 年前
        1
  •  11
  •   R Samuel Klatchko    15 年前

    因为 const double Shape::pi = 3.14159265; 是的定义 Shape::pi 而C++只允许一个符号的单个定义(称为 one-definition-rule 你可以在它的缩写形式ODR中看到。当定义在头文件中时,每个翻译单元都会得到自己的定义,这违反了规则。

    通过将其移动到源文件中,您只能得到一个定义。

        2
  •  12
  •   Potatoswatter    15 年前

    静态浮点数据成员必须在源文件中定义和初始化。一个定义规则禁止在 class {} 头中的块,并且只允许在 类{} 块。

    这也是不幸的,因为作为一个代数值,手头有即时值可能是很好的优化,而不是从全局变量加载。(不过,这种差异可能无关紧要。)

    不过,还是有办法的!

    class Shape
    {
    public:
        static double pi()
            { return 3.14159265; }
    
    private:
        double originX;
        double originY;
    };
    

    class{} 块。

    另外,我建议使用 M_PI <math.h> ,你也应该从中得到 <cmath> .

        3
  •  9
  •   Benjamin    7 年前

    如果你有办法增加 C++0x 标记到编译器,您将能够执行以下操作:

    ifndef SHAPE_H
    #define SHAPE_H
    
    class Shape
    {
    public:
    
        static constexpr double pi = 3.14159265;
    private:
        double originX;
        double originY;
    };
    
    #endif
    

    C++0X 您可以将常量表达式用于除整型以外的其他类型。这使您能够就地声明和定义常量变量。

        4
  •  3
  •   Viet    7 年前

    发生这种情况是因为不能多次定义shape::pi。在shape.cpp中包含shape.h时定义一次,在其他cpp文件中使用shape.h时定义一次。当你将程序链接在一起时,链接器会因为多重定义而死机。

        5
  •  1
  •   zmbush    15 年前

    线 const double Shape::pi = 3.14159265; 应该在shape.cpp文件中。头文件用于声明变量。只能定义一次变量,因此必须在 .cpp . 头文件说明如何使用这些变量和函数,cpp文件说明如何操作。

        6
  •  0
  •   Oliver    15 年前

    对于基元数据类型(如int、double但不是char[]),还可以在头文件中的类定义内定义常量,例如:

    class Shape
    {
    public:
        static const double pi = 3.14159265;
    
    private:
        double originX;
        double originY;
    };
    

    这将允许更好的编译器优化。

    编辑: 正如丹尼斯在下面指出的,这只允许用于整数类型,而不允许用于double或float数据类型(不过有些编译器会允许)。

        7
  •  0
  •   pacholik    8 年前

    实现一个函数,该函数将值的索引(如果存在)返回到列表。否则,如果没有值,则返回-1。如果同一个值在列表中存在多次,则从底部删除第一个值。

    public static intfindFromLast (List <Double> l, double value ) {///…}