Search code examples
c++visual-studio-2010headeriar

Visual Studio C++ Headers


I need to create structure like this:

// file main.h:
#pragma once

#ifndef _MAIN_H
#define _MAIN_H

#include <iostream>

#include "first.h"
#include "second.h"

#endif
// -----------------

// file first.h:
#pragma once

#ifndef _FIRST_H
#define _FIRST_H

#include "main.h" // because of using SomeFunction() in first.cpp

int SomeVar; // used in first.cpp

#endif
// -----------------

// file second.h:
#pragma once

#ifndef _SECOND_H
#define _SECOND_H

#include "main.h" // because of using SomeVar in second.cpp

int SomeFunction(); // implemented in second.cpp

#endif
// -----------------

By logic, if main.h will be compiled first, then each of this headers will be included only once and all variables/functions will be defined normally.

For example, this configuration compiled normally in IAR C++ Compiler, if set up in options "preinclude file" (not precompiled) to main.h.

But, in Visual Studio 2010 same structure causes linker errors like:

1>second.obj : error LNK2005: "int SomeVar" (?SomeVar@@3HA) already defined in first.obj
1>second.obj : error LNK2005: "int SomeFunction" (?SomeFunction@@3HA) already defined in first.obj

I think because of including files in alphabetic order. Apparently pragma- and define-guards are ignored by linker.

Errors can be fixed by additional header and external variables definitions, but this is hard and wrong way.

Question is: What should i do?


Solution

  • int SomeVar; // used in first.cpp
    

    Variables should never be defined in headers. They should be declared with extern:

    extern int SomeVar; // used in first.cpp
    

    Then you can actually define them in "first.cpp" with int SomeVar;.


    Also, "first.h" does not need to include "main.h". Headers should only include files if the definitions in that header absolutely need the contents of those files. The definitions in "first.h" do not need anything in "main.h". Therefore, it should not include it.

    If "first.cpp" needs to include something from "second.h", then it is the responsibility of "first.cpp" to include it.