3

I have a class called UIHandling inside a header file called UIHandling.h. At the top of the class I made sure to use:

#ifndef _UIH_
#define _UIH_

And of course ended the file with #endif

This header file consists all the implementations of the constructors. I've include this class in many files in my program but for some reason, I get the following compiler error:

1>CompaniesMap.obj : error LNK2005: "public: __thiscall UIHandling::UIHandling(enum eType)" (??0UIHandling@@QAE@W4eType@@@Z) already defined in Bond.obj
1>CompaniesMap.obj : error LNK2005: "public: __thiscall UIHandling::UIHandling(void)" (??0UIHandling@@QAE@XZ) already defined in Bond.obj
1>Company.obj : error LNK2005: "public: __thiscall UIHandling::UIHandling(enum eType)" (??0UIHandling@@QAE@W4eType@@@Z) already defined in Bond.obj
1>Company.obj : error LNK2005: "public: __thiscall UIHandling::UIHandling(void)" (??0UIHandling@@QAE@XZ) already defined in Bond.obj
1>Date.obj : error LNK2005: "public: __thiscall UIHandling::UIHandling(enum eType)" (??0UIHandling@@QAE@W4eType@@@Z) already defined in Bond.obj
1>Date.obj : error LNK2005: "public: __thiscall UIHandling::UIHandling(void)" (??0UIHandling@@QAE@XZ) already defined in Bond.obj
1>GovStock.obj : error LNK2005: "public: __thiscall UIHandling::UIHandling(enum eType)" (??0UIHandling@@QAE@W4eType@@@Z) already defined in Bond.obj
1>GovStock.obj : error LNK2005: "public: __thiscall UIHandling::UIHandling(void)" (??0UIHandling@@QAE@XZ) already defined in Bond.obj
1>main.obj : error LNK2005: "public: __thiscall UIHandling::UIHandling(enum eType)" (??0UIHandling@@QAE@W4eType@@@Z) already defined in Bond.obj
1>main.obj : error LNK2005: "public: __thiscall UIHandling::UIHandling(void)" (??0UIHandling@@QAE@XZ) already defined in Bond.obj
1>Stock.obj : error LNK2005: "public: __thiscall UIHandling::UIHandling(enum eType)" (??0UIHandling@@QAE@W4eType@@@Z) already defined in Bond.obj
1>Stock.obj : error LNK2005: "public: __thiscall UIHandling::UIHandling(void)" (??0UIHandling@@QAE@XZ) already defined in Bond.obj
1>D:\Asaf\C\VS\hw5\HW5\Debug\HW5.exe : fatal error LNK1169: one or more multiply defined symbols found

So I went to Bond.h and Bond.cpp to see if there's anything strange (Like an implementation of UIHandling::UIHandling() or something like that) and there isn't.

I saw in another question that this error shows when you violate the ODR, but I didn't. In another similar question the answer was that this has something to do with including the same file over and over causing many different implementations of the constructor, but that is avoided using the #ifndef _UIH command.

It may have something to do with how I declare and define my constructors: In UIHandling.h:

class UIHandling : public exception
{
public:
    UIHandling();           // Default C'tor - error unknown
    UIHandling(eType);      // C'tor with error type
    template <class T>
    UIHandling(eType, T);   // C'tor with error type and relevant number
...
}
...
UIHandling::UIHandling()
{
...
}

UIHandling::UIHandling(eType e)
{
...
}

template <class T>
UIHandling::UIHandling(eType e, T number)
{
...
}

Any help?

Community
  • 1
  • 1
asaf92
  • 1,557
  • 1
  • 19
  • 30
  • "In another similar question the answer was that this has something to do with including the same file over and over causing many different implementations of the constructor, but that is avoided using the #ifndef _UIH command." -- You're very much misreading the answers there. No, `#ifndef _UIH` doesn't prevent the same header file from being included in multiple source files, nor should it. –  Jun 13 '16 at 10:37
  • So what does it even do? – asaf92 Jun 13 '16 at 10:42
  • It prevents the same header file from being included multiple times in a single source file. –  Jun 13 '16 at 11:11
  • So why are the functions implemented over and over if it prevents the header file that implements them from being included? I do not understand. – asaf92 Jun 13 '16 at 12:16

1 Answers1

3

If you are defining the member functions outside the class and in the header, you need to use the inline keyword and make sure the header's content is only included once per translation unit (i.e. per cpp file, this is done with header include guards or a #pragma once).

class UIHandling : public exception
{
public:
    UIHandling();
    // ...
};

inline // << add this...
UIHandling::UIHandling()
{
}

The cppreference for inline;

An inline function is a function with the following properties:

  1. There may be more than one definition of an inline function in the program as long as each definition appears in a different translation unit. For example, an inline function may be defined in a header file that is #include'd in multiple source files.
  2. The definition of an inline function must be present in the translation unit where it is called (not necessarily before the point of call).
Niall
  • 30,036
  • 10
  • 99
  • 142
  • Why? Why can't i include `UIHandling.h` as many times as I want as long as it has `#pragma once` or `#ifndef` at the top? – asaf92 Jun 13 '16 at 10:37
  • @PanthersFan92. You can, it emphasis is on the content. I'll edit it to make it more clear. The include guards will ensure that the content is removed if it is already present in the TU. – Niall Jun 13 '16 at 10:40
  • But I did use `#ifndef` so why do I need to use `inline`? those implementations won't occur twice. – asaf92 Jun 13 '16 at 10:40
  • And all those implementations were inside the `.h` file not the `.cpp` (I actually didn't use `.cpp` for the `UIHandling` class. – asaf92 Jun 13 '16 at 10:41
  • The `inline` is there for the linker; it allows for multiple definitions over the translation units. If the inline is missing, then linker sees these multiple definitions with external linkage and fails to compile. – Niall Jun 13 '16 at 10:43
  • @PanthersFan92. See here; http://en.cppreference.com/w/cpp/language/inline – Niall Jun 13 '16 at 10:45