Forward declarations for variables?

2020-07-06 05:07发布

问题:

I have some C code that I have to port to C++. The code has a structure

struct A { 
    ...
    struct A * myPtr;
}

And now two global arrays are declared and initialized like this:

//Forward declaration of Unit
struct A Unit[10];

struct A* ptrUnit[2] = { Unit, Unit+7 };
struct A Unit[10] = { { .., &ptrUnit[0] }, 
                      ... };

Now while this works fine in C, it gives an error in C++ (variable redeclared). Aren't variables allowed to be forward-declared in C++?

回答1:

In C++, a variable declaration must be prefixed with extern:

extern A Unit[10];

// ...

A Unit[10] = { ... };

(Note that in C++ you can omit the leading struct.)



回答2:

struct A Unit[10] is not a forward declaration of a variable. The term "forward declaration" normally refers to non-defining declarations, while struct A Unit[10] is a definition. So in your code you are defining Unit multiple times in the same source file. In C language it is allowed, since in C definitions without an initializer are tentative definitions. They may occur many times in the same translation unit. In C++ there's no such thing as tentative definition. In C++ multiple definitions are always illegal.

If you want a genuine forward declaration for a variable, you have to use the keyword extern

extern struct A Unit[10];

This will work in both C and C++. However, as a side effect, this will give Unit external linkage. If you need a variable with internal linkage, then you are out of luck in C++, since in C++ it is not possible to forward-declare a variable with internal linkage. Meanwhile, in C tentative definitions will still help you to achieve that.



回答3:

C allows variables to be tenatively declared (I guess). C++ does not. Once 'Unit' has been defined, it cannot be redefined in the same scope



回答4:

Make Unit a function that returns a reference to to A[10] and have the actual array be a static variable in the function.

// in hpp file
A[10]& Unit();

// in cpp file
A[10]& Unit() {
    static A[10] value;
    return value;
}