如何在 C++ 类中创建 const 数组和计算 const 值?

Posted

技术标签:

【中文标题】如何在 C++ 类中创建 const 数组和计算 const 值?【英文标题】:How do I create const arrays and calculated const values in C++ class? 【发布时间】:2009-05-14 15:44:26 【问题描述】:

我遇到了一些我不理解的编译器错误。我很确定我在这里做错了什么,但我不知道是什么。我希望将所有世界常量定义为属于该类。

注意事项:

我只使用类作为带有附加成员的结构。我不是故意遵循严格的面向对象设计。请不要评论公共变量。

我不太关心编译器内联的东西。我使用这种结构是因为它易于使用。 (如果有效)

class Board
public:
    enum PhysicsResult BOUNCE, OUT_OF_BOUNDS_TOP, OUT_OF_BOUNDS_BOTTOM, CONTINUE ;
    //World constants
    const static float Height = 500;
    const static float Width = 300;
    //ERROR: 'Board::Width' cannot appear in a constant-expression.
    const static float PaddleWidth = Width/15; 
    const static float BallRadius = 5;
    const static float BounceDistance = 1.5;
    //World Objects
    Ball ball;
    Paddle paddle1;
    Paddle paddle2;
    /*
     1---2
     |   |
     0---3
     */
    //ERROR: a brace-enclosed initalizer is not allowed here before '' token
    //ERROR: invalid in-class initalization of static data member of nonintegral type 'const Pair[4]'
    const static Pair corners[4] = Pair(0, 0), Pair(0, Height), Pair(Width, Height), Pair(Width, 0);

    //ERROR: a brace-enclosed initalizer is not allowed here before '' token
    //ERROR: invalid in-class initalization of static data member of nonintegral type 'const Pair[2]'
    const static Pair left_wall[2]   = corners[0], corners[1];

    //ERROR: a brace-enclosed initalizer is not allowed here before '' token
    //ERROR: invalid in-class initalization of static data member of nonintegral type 'const Pair[2]'
    const static Pair right_wall[2]  = corners[3], corners[2];

    //ERROR: a brace-enclosed initalizer is not allowed here before '' token
    //ERROR: invalid in-class initalization of static data member of nonintegral type 'const Pair[2]'
    const static Pair top_wall[2]    = corners[1], corners[2];

    //ERROR: a brace-enclosed initalizer is not allowed here before '' token
    //ERROR: invalid in-class initalization of static data member of nonintegral type 'const Pair[2]'
    const static Pair bottom_wall[2] = corners[0], corners[3];

如果可以这样做,那么正确的语法是什么? 如果这不可能,我应该使用什么替代方法?

【问题讨论】:

【参考方案1】:

在类的主体之外定义静态常量,使用 gcc 编译和执行。

#include <iostream>
using namespace std;

struct Pair  int a; int b; Pair(int x, int y) : a(x),b(y) ;
struct F 
  static const float blah = 200.0;
  static const Pair corners[4];
;

// square boards are so ordinary
const Pair F::corners[4] =  Pair(0,0), Pair(0,1), Pair(2,0), Pair(2,2) ;

const float F::blah ;

int main(int, char **) 
  cout << F::corners[0].a << endl ;
  cout << F::blah << endl;
  return 0;

ebo 关于初始化顺序的评论的重要性怎么强调都不为过。

【讨论】:

您可能需要解决[静态初始化顺序问题][1] [1]:parashift.com/c++-faq-lite/ctors.html#faq-10.13 只要把它们放在同一个文件中,它们就会按顺序初始化。 我担心董事会将在一个文件(board.cpp)中,董事会用户将在另一个文件(game.cpp)中,会有Game的静态成员引用Board 的角落,并且根据 board.obj 和 game.obj 链接的顺序,程序将神秘地运行或崩溃。 如果你必须从其他翻译单元访问 F::corners,你也可以去掉 Pair 构造函数,像 const Pair F::corners[4] = 0, 0 , 0, 1 , ..... ;对象将在任何其他初始化发生之前初始化,然后直接在所有内容的零初始化之后进行(静态初始化。重要的是所有初始化表达式必须是常量表达式,并且数组是 POD 类型)。然后,您可以在运行时初始化的代码中安全地访问它(动态初始化) Thomas:对我的应用程序来说不是问题。 Paddle、Board 和 Ball 是代码中唯一的“对象”。其他一切都在全局函数中。我正在为程序的图形使用 OpenGL,所以我跳过了这个项目的 OOP。【参考方案2】:

您必须在构造函数初始化列表中初始化 const 成员。

class blah

    public:
            blah() : _constant( 1 )  

    private:
            const int _constant;
;

【讨论】:

什么是“构造函数初始化列表”? parashift.com/c++-faq-lite/ctors.html#faq-10.6 初始化器列表是您在成员上调用构造函数的方式。在上面的例子中,它是 ":_constant(1)" 部分。如果您需要多个,请用逗号分隔它们。即 blah() : _constant(1)、_constant1(2)、_constant2(3) 等... @mgb:不幸的是,没有办法使用初始化列表来初始化静态数据。此外,以下划线开头的标识符通常是不好的做法。我认为在这种情况下没关系,因为它后面跟着一个小写字母,但这仍然不是最佳实践,尤其是在 C++ 新手的示例中。见***.com/questions/228783/… 这会因 const 静态变量而失败。【参考方案3】:

C++ 对象的静态成员需要在声明之外定义。这是因为编译器不知道将成员放入哪个翻译单元(.o 文件)。

通常我会在实现的 .cpp 文件中定义它们。您通常不希望将它们放入头文件中,因为它们最终会出现在多个 .o 文件中,并且会产生编译器错误,因为多次定义了相同的东西。

【讨论】:

很高兴知道未来。我现在将所有代码都放在标题中。

以上是关于如何在 C++ 类中创建 const 数组和计算 const 值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中的子类中创建父对象数组?

在 C++ 中的类中创建类对象的动态数组

在C++ 如何在堆中创建一个类的对象? 谢谢!

在 C++ 中创建对三元运算符结果的 const 引用是不是安全?

如何复制动态分配的对象(具有一个类的 const 成员)

如何根据字符串数量的输入在 C++ 中创建数组?