LNK2005/LNK1169: one or more multiply defined defined symbols found

Edited: It seems there is a protocol for putting free functions in header files [1]

I've created a Visual Studio project to collect and organize some scrap code/examples that can be considered "related to polymorphism". I thought to do this by using namespaces to keep examples separate. Below, you can see I've defined a VirtualTables namespace, some classes within it, and a "free" function void Example3().

I thought to use header guards because VirtualTables.cpp already defines the namespace (and everything else inside) and I figured the line #include "VirtualTables.cpp" inside ex_Polymorphism.cpp would attempt to redefine the namespace (et al.). But header guards didn't fix the issue.

I get a linker error when building this project:

1>------ Build started: Project: ex_Polymorphism, Configuration: Debug Win32 ------
1>ex_Polymorphism.cpp
1>ex_Polymorphism.obj : error LNK2005: "void __cdecl VirtualTables::Example3(void)" (?Example3@VirtualTables@@YAXXZ) already defined in VirtualTables.obj
1>C:\Users\PC\Desktop\Code\C++\Scrapcode\ex_Polymorphism\Debug\ex_Polymorphism.exe : fatal error LNK1169: one or more multiply defined symbols found
1>Done building project "ex_Polymorphism.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========



ex_Polymorphism.cpp
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include "VirtualTables.cpp"

int main()
{
    VirtualTables::Example3();

    int pauseConsole;
    std::cin >> pauseConsole;
    return 0;
}


VirtualTables.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#ifndef VIRTUALTABLES_CPP
#define VIRTUALTABLES_CPP

namespace VirtualTables
{
    struct A
    {
        virtual void Function1()
        {
            std::cout << "A::Function1 Called!\n";
        }
    };

    struct B : A
    {
        void Function1() override
        {
            std::cout << "B::Function1 Called!\n";
        }
    };

    void Example3()
    {
        A a = B();
        a.Function1(); // "A::Function1 Called!\n"

        B b = B();
        A *aptr = &b;
        aptr->Function1(); // "B:Function1 Called!\n"
    }
}
#endif 


[1] SO: putting function definitions in header files
https://stackoverflow.com/q/7833941/5972766
Last edited on
Oddly, if I make void Example3() inline:

1
2
3
4
5
6
7
8
9
    inline void Example3()
    {
        A a = B();
        a.Function1(); // "A::Function1 Called!\n"

        B b = B();
        A *aptr = &b;
        aptr->Function1(); // "B:Function1 Called!\n"
    }


the problem goes away. Inlining [1] a function replaces everywhere it's called with the instructions inside that function, as if the function call never occurred at all (e.g., arguments and return values aren't pushed onto another call stack). But to the compiler, an inline function is still a function right? So why don't we have the same problem?

[1] https://www.cplusplus.com/articles/2LywvCM9/
Hello ElusiveTau,

When you look at the "Solution Explorer" under "Source Files" Is there 1 or more ".cpp" files?

If there are 2 files each is compiled separately. Which means that you are compiling and linking the same code twice.

One way to avoid this is to name the file "VirtualTables" as "VirtualTables.hpp".

The other would be to remove "VirtualTables.cpp" from the project so it does not compile until it is included in with the "main" function.

Andy
If you are linking in the same code twice, that is why using inline works. See point 2. under explanation in:

https://en.cppreference.com/w/cpp/language/inline
Handy Andy wrote:

When you look at the "Solution Explorer" under "Source Files" Is there 1 or more ".cpp" files?


No, just the two .cpp files as specified in my original post.

I've implemented your first suggestion:

VirtualTables.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>

namespace VirtualTables
{
    struct A
    {
        virtual void Function1()
        {
            std::cout << "A::Function1 Called!\n";
        }
    };

    struct B : A
    {
        void Function1() override
        {
            std::cout << "B::Function1 Called!\n";
        }
    };

    void Example3()
    {
        A a = B();
        a.Function1(); // "A::Function1 Called!\n"

        B b = B();
        A *aptr = &b;
        aptr->Function1(); // "B:Function1 Called!\n"
    }
}


ex_Polymorphism.cpp
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include "VirtualTables.hpp"

int main()
{
    VirtualTables::Example3();

    int pauseConsole;
    std::cin >> pauseConsole;
    return 0;
}


But I get the same error. What does compile is replacing the definition for Example3() with a declaration and providing the implementation elsewhere:

VirtualTables.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>

namespace VirtualTables
{
    struct A
    {
        virtual void Function1()
        {
            std::cout << "A::Function1 Called!\n";
        }
    };

    struct B : A
    {
        void Function1() override
        {
            std::cout << "B::Function1 Called!\n";
        }
    };

    void Example3(); // Now just a declaration
}

/* Error if you try to provide implementation here
void VirtualTables::Example3()
{
    A a = B();
    a.Function1(); // "A::Function1 Called!\n"

    B b = B();
    A *aptr = &b;
    aptr->Function1(); // "B:Function1 Called!\n"
}
*/


VirtualTables.cpp
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include "VirtualTables.hpp"

void VirtualTables::Example3()
{
    A a = B();
    a.Function1(); // "A::Function1 Called!\n"

    B b = B();
    A *aptr = &b;
    aptr->Function1(); // "B:Function1 Called!\n"
}


ex_Polymorphism.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "VirtualTables.hpp"

/* Will compile here
void VirtualTables::Example3()
{
    A a = B();
    a.Function1(); // "A::Function1 Called!\n"

    B b = B();
    A *aptr = &b;
    aptr->Function1(); // "B:Function1 Called!\n"
}
*/

int main()
{
    VirtualTables::Example3();

    int pauseConsole;
    std::cin >> pauseConsole;
    return 0;
}


Last edited on
Hello ElusiveTau,

For VirtualTables.cpp try this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

#include "VirtualTables.hpp"

namespace VirtualTables
{
    void Example3()
    {
        A a = B();
        a.Function1(); // "A::Function1 Called!\n"

        B b = B();
        A *aptr = &b;
        aptr->Function1(); // "B:Function1 Called!\n"
    }
}

Since your function is in a different file you will need to wrap it in the same name space.

When I did this my VS2017 compiled with no errors.

Andy
I'm a bit confused because [1] suggests that defining functions in a namespace should be possible.

There's another point [2] that doesn't seem to be true. Since this won't compile (here, I try to define the namespace in the VirtualTables.hpp/.cpp file.

VirtualTables.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>

namespace VirtualTables
{
    struct A
    {
        virtual void Function1()
        {
            std::cout << "A::Function1 Called!\n";
        }
    };

    struct B : A
    {
        void Function1() override
        {
            std::cout << "B::Function1 Called!\n";
        }
    };

    void Example3();
};


VirtualTables.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include "VirtualTables.hpp"

// We expect this declaration here to extend the declaration from VirtualTables.hpp
namespace VirtualTables
{
    void Example4();
}

void VirtualTables::Example3()
{
    A a = B();
    a.Function1(); // "A::Function1 Called!\n"

    B b = B();
    A *aptr = &b;
    aptr->Function1(); // "B:Function1 Called!\n"

    Example4(); // This call is OK!
}

// This definition seems to be local to just this file
void VirtualTables::Example4()
{
    std::cout << "Hello from Example4!\n";
}


ex_Polymorphism.cpp
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include "VirtualTables.hpp"

int main()
{
    VirtualTables::Example3();
    VirtualTables::Example4(); // Error: Namespace VirtualTables has no member "Example4"!

    int pauseConsole;
    std::cin >> pauseConsole;
    return 0;
}



[1] C++ Primer 5'th Edition, Lippman, pp. 963 "18.2.1. Namespace Definitions"
A namespace definition begins with the keyword namespace followed by the namespace name. Following the namespace name is a sequence of declarations and definitions delimited by curly braces. Any declaration that can appear at global scope can be put into a namespace: classes, variables (with their initializations), functions (with their definitions), templates, and other namespaces: ...


[2] Ibid., pp. 964 "Namespaces Can be Discontinuous"
The fact that namespace definitions can be discontiguous lets us compose a
namespace from separate interface and implementation files. Thus, a namespace can
be organized in the same way that we manage our own class and function definitions:

• Namespace members that define classes, and declarations for the functions and
objects that are part of the class interface, can be put into header files. These
headers can be included by files that use those namespace members.
• The definitions of namespace members can be put in separate source files.
Organizing our namespaces this way also satisfies the requirement that various entities
—non-inline functions, static data members, variables, and so forth—may be defined
only once in a program.
Last edited on
Hi,

One generally shouldn't put implementation code in a header file: each time the header is included somewhere, it breaks the One Definition Rule (ODR). Note that std::cout is implementation. Of course one can inline a function, but only do this with trivial functions.

So the header file should contain function declarations, not function definitions. The definitions of functions go in the relevant cpp file.

With namespaces, in the header file put the whole class definition inside a namespace with braces, as you did in VirtualTables.hpp

In the cpp file use the namespace scope with each function definition, as in:

1
2
3
4
void VirtualTables::Example3()
{
   //  ....
}


Hope this helps :+)
Topic archived. No new replies allowed.