Replacing macro with const [keyword "extern"]

Hi guru,

I heard that const shall be preferred over #define
So I start to change my program accordingly.

But then below error message occurs during compilation:
In file included from particle.cpp:5:0:
particle.h:9:31: error: array bound is not an integer constant before ‘]’ token

Let's look at the code.
This project consists of 5 files below.

File 1: main.cpp
1
2
3
4
5
6
7
8
9
#include "common.h"
#include "definition.h"
#include "particle.h"

int main()
{
    Particle *p = new Particle();
    return 0;
}


File 2: common.h
(This is where all the extern are defined. This file is included by all other files.)
1
2
3
4
5
6
#ifndef COMMON_H_INCLUDED
#define COMMON_H_INCLUDED

extern const int dimension;

#endif // COMMON_H_INCLUDED 


File 3: definition.h
(This file is included by only main(), not any other files)
1
2
3
4
5
6
7
8
#ifndef DEFINITION_H_INCLUDED
#define DEFINITION_H_INCLUDED

#include "common.h"

const int dimension  =  2;

#endif // DEFINITION_H_INCLUDED 


File 4: particle.h (class definition header file)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef PARTICLE_H_INCLUDED
#define PARTICLE_H_INCLUDED

#include "common.h"

class Particle
{
    protected:
      static float X[dimension];

    public:
      Particle();
};


#endif // PARTICLE_H_INCLUDED 


File 5: particle.cpp (class declaration)
1
2
3
4
5
6
7
8
9
#ifndef PARTICLE_CPP_INCLUDED
#define PARTICLE_CPP_INCLUDED

#include "common.h"
#include "particle.h"  // some problem solved when this line is removed.

Particle::Particle()  { }

#endif // PARTICLE_CPP_INCLUDED 


I guess the error occurs because, when the line 9 of particle.h (File 4) is compiled, value of const int dimension is not seen by the compiler.

But how to solve it, or any workaround ..?

Thanks in advance.
Last edited on
Global variables go in source .cpp files, not header .h files.

dimension.cpp const int dimension = 2

definition.h will not be needed anymore.

Be advised, dimension.cpp needs to be compiles too, just like all other .cpp files.

Header guards are only needed for headers.

particle.cpp
1
2
3
4
5
6
7
8
9
#ifndef PARTICLE_CPP_INCLUDED
#define PARTICLE_CPP_INCLUDED

#include "common.h"
#include "particle.h"  // some problem solved when this line is removed.

Particle::Particle()  { }

#endif // PARTICLE_CPP_INCLUDED  


Edit:
Also, static data members, like your Particle::X[] also need to go in their own .cpp file.
http://www.parashift.com/c++-faq/link-errs-static-data-mems.html

Edit 2: I was wrong in the first part, see JLBorges' post.

Edit 3: http://stackoverflow.com/questions/998425/why-does-const-imply-internal-linkage-in-c-when-it-doesnt-in-c#
Last edited on
Just define the constant in the included header common.h
(Constants have internal linkage, you can include that header in multiple translation units.)

1
2
3
4
5
6
7
8
#ifndef COMMON_H_INCLUDED
#define COMMON_H_INCLUDED

//extern const int dimension; // *** no extern, we want internal linkage
const int dimension = 2 ;
// or: constexpr int dimension = 2 ; // C++11 

#endif // COMMON_H_INCLUDED  


And just throw definition.h away; it is not required
I would like to append @JLBorges answer.
Any array needs a constant expression as its dimension that is known at compile-time.
The error message says about this clear enough:

particle.h:9:31: error: array bound is not an integer constant before ‘]’ token

Now let consider your files. File particle.h contains declaration of class Particle that has data member of a compound type

static float X[dimension];

So the compiler has to know what is the value of variable dimension that shall be defined as constant.

This file does not contain the definition of the variable dimension. However it includes another file "common.h". File "common.h" contains the following declaration

extern const int dimension;

It is not a definition of the constant. It is only a declaration that says that somewhere there is the definition of the constant. But the compiler does not this definition. So it ccan not calculate how much memory the class occupies. And it issues the error, definition.h, that contains a definition of constant with name dimension

const int dimension = 2;

But constant objects have internal linkage. So this definition and the declaration in header

You also have one more header file "common.h" declare different names.

One of which has external linkage and was not defined. The other has internal linkage and visible only in the module that includes header "common.h".

You need not to declare this constant as external. It is enough to define it in some header file and include this header where the definition of the constant is required.
Last edited on
Thanks Catfish3, JLBorges and vlad.

In fact I need to define const int dimension = 2 as global variable and make this global to all (or almost all) header and cpp files in the project. I heard the best way to define global variable is to declare it as extern in one header file, then use a source file to define the variable. Is this recommendation correct..?
http://stackoverflow.com/questions/1433204/what-are-extern-variables-in-c

Nevertheless, when declared as extern, it doesn't work.
Last edited on
I heard the best way to define global variable is to declare it as extern in one header file, then use a source file to define the variable. Is this recommendation correct..?
http://stackoverflow.com/questions/1433204/what-are-extern-variables-in-c
[...]
How to solve the error, while still declaring dimension as extern?

What the others are telling you is that, in C++, for const variables, you don't need to declare them as extern. You can simply put const int dimension = 2; into a header file, and include it in any source file that needs to use that constant.
oh I see, thanks.
Without the extern keyword, everything work !
So, problem solved.

Thanks everyone.
Last edited on
Topic archived. No new replies allowed.