News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

static members in C++

Started by redskull, June 17, 2010, 11:38:30 PM

Previous topic - Next topic

redskull

Does anybody know the how, why, or if static member declarations are exempt from the preprocessor?  Consider this situation

Class A is declared in a header file, and has a protected static member 'x'.  x is declared in the header file, but within the preprocessor block.  E.G.
#ifndef foo
#define foo
class A {
protected:
  static int x;
};
int A::x = 0;
#endif

Then, other classes which derive from A include the same A header file, but also their own B, C, D, etc, as necessary.  They compile fine, but when I link it all togehter, I get a 'duplicate symbol' errors for A for every module that included the A header file.  If i move the static declaration out of the .h and into the .cpp, everything links as necessary.

Are these static declarations exempt from the preprocessor?  Since there's a possibility the other, inhereted modules get compiled first, does the declaration of the protected member *have* to be in the module of the top-level class?   Is there any sort of rule or spec that goes into this?  It's with MSVC.

Always another 'gotcha' with C++, that's for sure

-r

Strange women, lying in ponds, distributing swords, is no basis for a system of government

akane

Hi redskull,
Just move "int A::x = 0;" to the module with class A implementation. This line will actually allocate memory for x.
The same error you can get with normal variables. "extern int x;" in a header is ok, but with assigned value is not ok (if two or more modules are including that header).

Optionally you could keep "int A::x = 0;" in your header, but protenced by another #ifdef:

#ifndef foo
#define foo
class A {
protected:
  static int x;
};
#ifdef A_cpp // begin a.cpp private defines
int A::x = 0;
#endif
#endif

file a.cpp
#define A_cpp
#include "a.h"

any other file:
#include "a.h"

bieber

What akane said.  The way you're doing it, each translation module that includes that header is creating a memory location for x when it hits

int A::X = 0;


When you try to link them all together, they all have their own locations set aside for the same symbol, and nastiness ensues.  As a general rule, make sure that you only declare things in header files, never assign them.