Reputation: 13356
I want to implement a function with OpenGL to render a cylinder in C++. The signature of my function is as follows:
#define POINTS_NUM 15
#define DEMESION 3
void drawCylinder( int slices, int segments, GLfloat (&vertices)[ POINTS_NUM ][ DEMESION ] );
I want to use a reference to a two-dimensional array to limit user input, but some strange behavior is happening. When I implement the function declared as above, an linker error occurs:
Error 1 error LNK2005: "float (* vase)[3]" (?vase@@3PAY02MA) already defined in shapes.obj vase.obj VaseAndAnimation
Here vase
is defined as:
GLfloat vase[ POINTS_NUM ][ DEMESION ];
At first, I thought there was something wrong with the last dimension. So I omitted it in my second trial. This time declaration of my function is like this:
void drawCylinder( int slices, int segments, GLfloat (&vertices)[ POINTS_NUM ][] );
Now a compile-time error occurs when invoked as (vase
definition isn't changed):
drawCylinder( 10, 10, vase );
Compile error:
Error 1 error C2087: 'vertices' : missing subscript d:\visual studio 2008\projects\project1\computer graphics\vaseandanimation\shapes.h 25 VaseAndAnimation
Error 2 error C2664: 'drawCylinder' : cannot convert parameter 3 from 'GLfloat [14][3]' to 'GLfloat (&)[14][1]' d:\Visual Studio 2008\Projects\Project1\Computer Graphics\VaseAndAnimation\vase.cpp 64 VaseAndAnimation
Error 3 error C2087: 'vertices' : missing subscript d:\visual studio 2008\projects\project1\computer graphics\vaseandanimation\shapes.h 25 VaseAndAnimation
Error 4 error C2087: 'vertices' : missing subscript d:\Visual Studio 2008\Projects\Project1\Computer Graphics\VaseAndAnimation\shapes.cpp 12 VaseAndAnimation
From this error, I can see that parameter vertices
is really treated a reference to a two-dimensional array, but why is vase
parsed as float (* vase)[3]
in my first version?
My IDE is Visual Studio 2008. I haven't tried it with GCC; is that behavior compiler-dependent?
Hope someone can give me a hand to get rid of the trap.
Upvotes: 5
Views: 471
Reputation: 54270
It looks like the problem is just that vase
is being defined in a header file. You should only declare variables in header files.
This causes a problem because the multiple definitions produce multiple of the same symbol, which confuses the linker (hence the linker error). When the linker tries to match up references to the variable to the actual definition, it doesn't know which one to use.
Header guards don't protect against this. The macros used in a header guard are only defined per translation unit. Every time your compiler starts to compile a new .cpp file (ignoring unity builds etc.), that's a new translation unit and essentially the compiler is starting from scratch, not knowing about any symbols that have been previously defined.
To fix this, only declare your variables in header files:
// extern specifies that the definition is elsewhere.
extern int myGlobalVariable;
and then define that variable in one source file.
int myGlobalVariable;
Upvotes: 1
Reputation: 99565
Your first declaration is fine. Seems to be you have defined vase
in a header file.
Upvotes: 2