C ++ - 在另一个头文件中包含一个头文件,以使全局变量可用于数组声明

时间:2017-03-04 02:28:58

标签: c++ arrays multidimensional-array global-variables header-files

我有一个名为WorldState的类,我想声明一个名为covar_matrix[dim][dim]的多维数组。全局变量dim属于int类型,在global.hglobal.cpp内声明和定义。以下是WorldState.h

的内容
#ifndef WORLDSTATE_H
#define WORLDSTATE_H
#include "global.h"

class WorldState{

    public:
        WorldState(float [], float [][dim]);
        get_wstate();


    protected:

    private:
        float w_state[];
        float covar_matrix[][dim];

};

#endif // WORLDSTATE_H

将一个标题(global.h)包含在另一个标题(WorldState.h)中是不错的做法?

它仍然会抛出错误:

||=== Build: Debug in slam (compiler: GNU GCC Compiler) ===|
C:\Users\syamp\Documents\codeblocks\slam\WorldState.h|8|error: array bound is not an integer constant before ']' token|
C:\Users\syamp\Documents\codeblocks\slam\WorldState.h|16|error: array bound is not an integer constant before ']' token|

如何在不通过构造函数传递任何大小的情况下声明此多维数组?

修改 global.h的内容:

#ifndef GLOBAL_H_INCLUDED
#define GLOBAL_H_INCLUDED

extern int marker_num;
extern constexpr int dim;

#endif // GLOBAL_H_INCLUDED

global.cpp

#include <iostream>
#include <cstdio>
#include <cmath>
#include "WorldState.h"
#include "Robot.h"
#include "Sensor.h"
#include "Marker.h"
#include "global.h"

int marker_num = 10;
constexpr int dim = (2 * marker_num) + 3;

5 个答案:

答案 0 :(得分:2)

不允许数组维度为任意变量。您需要将dim替换为常量。

答案 1 :(得分:1)

数组维度必须是C ++中的编译时常量。变量(即使声明为const)是不够的。您需要在C ++ 11之前使用constexpr(C ++ 11及更高版本)或文字值(如100)。如果要为维度命名,可以在C ++ 11之前使用宏(如#define DIM 100)。

没有什么可以阻止一个包含另一个的标头 - 预处理器只是进行文本替换,因此#include指令实际上被替换(复制/粘贴)该标头的内容。如果以递归方式完成(包括标题B的标题A,包括标题A),则必须使用包含保护的机制来阻止递归变为无限(这往往会使预处理器阻塞)。

答案 2 :(得分:1)

你应该在标题中声明你的'dim'变量:

extern const int dimm;

没有constexpr限定符。然后在global.cpp中你可以像这样实例化它:

constexpr const int dimm = 5;

或者像这样:

const int dimm = 5;

要么工作,因为编译器能够意识到第二个是隐式constexpr。

如果要计算同一语句中的值,则只能使用constexpr限定符。 但是,对于您手头的特定问题,我建议使用枚举:

enum {
    dimm = 5
};

枚举是纯编译时常量,在运行时不占用任何空间(如果你没有为它们的值赋值任何变量),并且在头文件中工作得很好。那个特殊的枚举是一个匿名的枚举,意思是它没有名字,只有一个值,dimm。

答案 3 :(得分:1)

我真的希望你能看到这一点,而且还没有继续你的生活。

在标题中定义常量数据并在整个应用程序中使用它绝对是一种很好的做法。对于您在整个应用程序中使用的一些静态函数也是如此;您可以创建一个Utility.h标题并存储您的实用程序功能(打印一些您通常使用的数学公式等)并在任何地方使用该标题。在其他标头中包含您自己的标头与包含其他人编写的标头(例如#include <iostream>)没有什么不同。

我个人不喜欢constexpr,但我也没有反对它的有效论据,只是偏好。对我来说,#define是一个更通用的东西,几乎意味着static constexpr const。当您使用#define时,您基本上告诉编译器将粘贴定义的值复制到其使用的位置。例如:

#define MAX_NUMBER 10
...

int cityLimit = MAX_NUMBER * 2;

编译器将MAX_NUMBER与您旁边的任何内容交换。它实际上是在复制和粘贴它。

以下是您的代码中不使用using namespace std的问题(特别是在您的全局声明或实用程序标头中)。 using namespace std从字面上获取整个命名空间内容并将其粘贴到它看到的任何位置。它会导致各种各样的问题,它完全是命名空间系统,尤其是在更大的代码库中,它会让其他开发人员不时地讨厌你。

大多数情况下,人们使用using namespace std来更快地撰写std::coutstd::endl。为此,您可以将using namespace std;更改为

using std::cout;
using std::endl;

它执行相同的操作但只从命名空间中获取这些函数而不是其中的所有内容。

答案 4 :(得分:0)

我发现最容易做的事情,也是一个不错的编程习惯,是:

#ifndef GLOBAL_H_INCLUDED
#define GLOBAL_H_INCLUDED

static constexpr const int marker_num = 10;
static constexpr const int dim = (2 * marker_num) + 3;

using namespace std;

#endif // GLOBAL_H_INCLUDED

以下是我收到的答案的链接:

Link1