0

There is a linker error in my SW. I am using the following structure based on h, hpp, cpp files. Some classes are templatized, some not, some have function templates. The SW contains hundreds of included classes...

Declaration:

test.h
#ifndef TEST_H
#define TEST_H

class Test
{
   public: 
        template <typename T>
        void foo1();

        void foo2 ();
};

#include "test.hpp" 

#endif

Definition:

test.hpp
#ifndef TEST_HPP
#define TEST_HPP

template <typename T>
void Test::foo1() {}

inline void Test::foo2() {} //or in cpp file

#endif

CPP file:

test.cpp
#include "test.h"

void Test::foo2() {} //or in hpp file as inline

I have the following problem. The variable vars[] is declared in my h file

test.h
#ifndef TEST_H
#define TEST_H

char *vars[] = { "first", "second"...};

class Test
{
    public: void foo();
};

#include "test.hpp"

#endif

and used as a local variable inside foo() method defined in hpp file as inline.

test.hpp
#ifndef TEST_HPP
#define TEST_HPP


inline void Test::foo() {
    char *var = vars[0];   //A Linker Error
}

#endif

However, the following linker error occurs:

Error   745 error LNK2005: "char * * vars" (?vars@@3PAPADA) already defined in main.obj

How and where to declare vars[] to avoid linker errors? After including

#include "test.hpp"

it is late to declare it...

As I wrote, the software contains a lot of cpp, and hpp files included each other (all includes have been checked). It is not possible to send the whole example...

The main.obj represents a file which contains the main class.

justik
  • 4,145
  • 6
  • 32
  • 53
  • 1
    Ifndef or ifndex? Are you getting a warning on that processor directive...? If it's not preventing double inclusion that might do it. Also, try to compile with -E to figure out where that 2nd definition comes from. – rutgersmike Nov 04 '12 at 22:57
  • @ RutgersMike: ifndef, of course, thanks, only a typo here... – justik Nov 04 '12 at 22:59
  • just a few typos in the code. ifndex to ifndef, void foo2 () need ';' in the end. remove '...' from *vars[]... – billz Nov 04 '12 at 23:01
  • @ billz. Thanks, checked and corrected (maybe),. Written without a compiler... – justik Nov 04 '12 at 23:03
  • err, wheres's test2.obj then??? – Roddy Nov 04 '12 at 23:04
  • It doesn't look like you're giving the real definition of `class Test`. You can't have two classes with the same name. And you declare one with `foo1` and `foo2` member functions, and then another with a `foo` member function. Are those all the same `class Test` and do they all need to be folded together? – Omnifarious Nov 04 '12 at 23:09

3 Answers3

3

Declare vars in the header with extern linkage

extern const char* vars[];

and define it in exactly one source file

const char* vars[] = {"foo", "bar"};

Note the const, the conversion from string literals to char* is deprecated. The way you have it now, you're violationg the One definition rule (You're redefining vars in every translation unit your header is included in).

Community
  • 1
  • 1
jrok
  • 54,456
  • 9
  • 109
  • 141
2

I think you just need this in test.hpp

extern char *vars[];

...and this in test.cpp

char *vars[] = { "first", "second"...};
Roddy
  • 66,617
  • 42
  • 165
  • 277
0

I assume you are not declaring two classes both named Test. If you are, that will cause you no end of problems. You are not allowed to do this.

So I assume the full declaration of class Test looks like this:

class Test
{
 public:
   void foo();

   template <typename T>
   void foo1();

   void foo2 ();
};

If this is the case, then your problem is clear.

You need to change the definition of vars. You need to have this in test.h:

extern char *vars[];

And this in test.cpp:

char *vars[] = { "first", "second"...};

Otherwise the compiler will think you're trying to declare a new version of vars in every file.

Omnifarious
  • 54,333
  • 19
  • 131
  • 194