How to include header and cpp without resulting in LNK2005 error in Visual Studio

1

The source code below is an abstraction of a code in production. But it is real, and the facts reported below apply to it.

The code compiles normally in GCG (linux), but in Visual Studio 2017 (windows), I get the error:

  

LNK2005 "public: int __cdecl XTEST :: Mt :: soma (int, int)" (? sum @ Mt @ XTEST @@ QEAAHHH @ Z) p>

main.cpp

#include "teste.cpp"
#include <stdio.h>

int main(){
    getchar();

    XTEST::Mt *t = new XTEST::Mt();

    printf("\n\nretorno = %d\n\n", t->soma(3, 5));

    delete t;

  return 0;
}

test.cpp

#pragma once

#ifndef TESTE_H
#define TESTE_H

#include "mhead.cpp"

#endif

mhead.h

#pragma once

#ifndef MT_H
#define MT_H

namespace XTEST {
    class Mt {
    public:
        int soma(int i, int d);
    };
}

#endif

mhead.cpp

#pragma once

#ifndef MT_CPP
#define MT_CPP

#include "mhead.h"

namespace XTEST {
    int Mt::soma(int i, int d) {
        return i + d;
    }
}
#endif

I'm a beginner in C ++ - especially in VS - but I know that ".h" should not - preferably - contain implementations, only declarations. So in the above case the ".h" contains only the class declaration, the whole implementation being placed in the ".cpp".

You may wonder why I have test.cpp . This is because the program has a large number of "modules". And in the production program, all the functionality of a module is nested in a ".cpp" file. These in turn must include the dependencies. Therefore, the existence of "test.cpp" is to maintain the equivalence of this code to true, which was omitted because of the size (more than 10,000 lines).

This ends up having the implementation in the mhead.obj , test.obj and main.obj in>, double. As far as I know this is the reason for the above error.

However, it is impossible to compile a code without including the ".cpp" - which contains the implementations. How to include both "h" and ".pp" , however allowing the entire program to access the functionality of the same?

NOTE: ".cpp" includes ".h", because ".cpp" requires the presence of declarations; but .h "does not include" .cpp "because" .h "can make use of external implementation, such as" .dll ".

Thank you.

ISSUE 1:

The response @lacobus is right (grateful) and solves the problem, but NOT conclusively. The above question includes the (implicit) compilation need in GCC, which may not have been clear, and the answer to that goal was also unclear. A specific compatibility question has been opened here .

    
asked by anonymous 01.10.2017 / 07:30

1 answer

2

Avoid #include 's of files that are not headers, this creates a "mess" without size!

It does not make sense to use #pragma once / #ifndef-#define in files .cpp ;

Do not mix #pragma once and #ifndef-#define , or one, or another.

OBS: Although the #pragma once directive is supported by most compilers, it is not part of the standard and may not work in some cases.

Here's an example (tested) illustrating something similar to what you're trying to do:

Mt.cpp

#include "Mt.h"

namespace Subsistema {
    int Mt::soma(int i, int d) {
        return i + d;
    }
}

My.cpp

#include "My.h"

namespace Subsistema {
    int My::sub(int i, int d) {
        return i - d;
    }
}

Mx.cpp

#include "Mx.h"

namespace Subsistema {
    int Mx::mul(int i, int d) {
        return i * d;
    }
}

Mt.h

#ifndef MT_H
#define MT_H

namespace Subsistema {
    class Mt {
    public:
        int soma(int i, int d);
    };
}

#endif

My.h

#ifndef MY_H
#define MY_H

namespace Subsistema {
    class My {
    public:
        int sub(int i, int d);
    };
}

#endif

Mx.h

#ifndef MX_H
#define MX_H

namespace Subsistema {
    class Mx {
    public:
        int mul(int i, int d);
    };
}

#endif

Subsystem.h

#ifndef SUBSISTEMA_H
#define SUBSISTEMA_H

#include "Mt.h"
#include "Mx.h"
#include "My.h"

#endif

main.cpp:

#include <iostream>

#include "Subsistema.h"

int main(void)
{
    Subsistema::Mt * t = new Subsistema::Mt();
    Subsistema::Mx * x = new Subsistema::Mx();
    Subsistema::My * y = new Subsistema::My();

    std::cout << "Soma: " << t->soma(3, 5) << std::endl;
    std::cout << "Multiplicacao: " << x->mul(3, 5) << std::endl;
    std::cout << "Subtracao: " << y->sub(3, 5) << std::endl;

    delete t;
    delete x;
    delete y;

    return 0;
}

Output:

Soma: 8
Multiplicacao: 15
Subtracao: -2
    
01.10.2017 / 13:04