четверг, 10 июня 2010 г.

Include guards is not all-healing

Once upon a time a got a linker error:
//файл testing.h
#ifndef TESTING_H
#define TESTING_H
class MyClass
{
private:
    int classData;
public:
    MyClass();
    ~MyClass();
};

namespace TestNS
{
    int namespaceData;
};
#endif
//файл testing.cpp
#include "Testing.h"

MyClass::MyClass()
{
 //........
}

MyClass::~MyClass()
{
 //........
};
//файл mainfile.cpp
#include "Testing.h"
int main()
{
    TestNS::namespaceData = 0;
    return 0;
}

(MSVC2008):
Error 1 error LNK2005: "int TestNS::namespaceData" (?namespaceData@TestNS@@3HA) already defined in Testing.obj mainfile.obj
Error 2 fatal error LNK1169: one or more multiply defined symbols found E:\test.exe
It seems strange at first glance since I use include guards, and all should be OK.
But they are intended to only avoid the problem of double inclusion.
The error occurs when the linker finds two matches that collide.

In our case there are two object files - mainfile.obj and testing.obj.
Each of them has TestNS::namespaceData. A solution is not to define the variable in the header file. It´s needed to be defined in the source file and only declared in the header fileby use extern directive

//file testing.h
namespace TestNS
{
    extern int namespaceData;
};
//file testing.cpp
namespace TestNS
{
 int namespaceData;
};
Now it works Another way to get rid of the error is to declare the variable as constant
//file testing.h
namespace TestNS
{
 const int namespaceData;
};