defining integral static const in a class whose .h file is included in multiple cpp files

911 Views Asked by At
A.h

class A  
{  
   private:
     static const int b = 50;
     int c[b];
 };

 A.cpp

 #include "A.h"
 const int A::b;

 C.cpp

 #include "A.h"

The compiler issues me a warning saying b is defined multiple times and one is ignored. I need to define it in the class since i need to initialize the array. Alternatively I would need to use the enum approach to do it. But I wanted to know if this was possible?

2

There are 2 best solutions below

5
On

I'm going to guess that you are using Visual C++, which has a rather horrible language extension, as described in "Microsoft Extensions to C and C++":

Out of Class Definition of static const Integral (or enum) Members

Under the standard (/Za), you need to make an out-of-class definition for data members. For example,

class CMyClass {
    static const int max = 5;
    int m_array[max];
}
...
const int CMyClass::max;   // out of class definition

Under /Ze, the out-of-class definition is optional for static, const integral, and const enum data members. Only integrals and enums that are static and const can have initializers inside a class; the initializing expression must be a const expression.

To avoid errors when an out-of-class definition is provided (when the out-of-class definition is provided in a header file and the header file is included in multiple source files), you should use selectany. For example:

__declspec(selectany) const int CMyClass::max = 5;

The /Ze flag is enabled by default. You have to explicitly use the /Za flag if you don't want the language extensions.

The code as written compiles and links as-is without error using g++ 4.5.2, Clang 3.0, and Visual C++ 2010 with the /Za flag set.

Removing the definition from the .cpp file resolves the issue if you want to compile with Visual C++, but then it won't work with other compilers (or with /Za) if you try to use the data member. For a portable workaround, you can use a conditional compilation block that checks to see whether the extensions are enabled:

#ifndef _MSC_EXTENSIONS
const int A::b;
#endif
1
On

You've given conflicting definitions. By giving the variable a value within the class definition, you're saying it's a compile-time constant that doesn't need any storage. Then you're trying to give it storage in the .cpp file.

Take it out of the .cpp and you'll be fine. Just don't try to take the address of it.