iKebab897
iKebab897

Reputation: 83

Linker errors in Visual Studio

I'm writing a C++ wxWidgets calculator application. I have this header file where I declare the various operations and constants that my app supports. When I try to compile, I get 258 LNK2005 errors, such as:

Error LNK2005 "bool __cdecl isBinary(class wxString)" (?isBinary@@YA_NVwxString@@@Z) already defined in app.obj C:\Users\giorg\Desktop\Visual Studio\wxWidgetsTest\wxWidgetsTest\events.obj 1 ikeCalculator

Error LNK2005 "class wxString unary::tan" (?tan@unary@@3VwxString@@A) already defined in app.obj C:\Users\giorg\Desktop\Visual Studio\wxWidgetsTest\wxWidgetsTest\events.obj 1 ikeCalculator

And so on for everything in this file. There seems to be an error for every time one of these objects is referenced in other files.

#pragma once
#include "wx/wx.h"
#include <cmath>
#include <map>

namespace binary {
    wxString add(L"+"), sub(L"-");
    wxString mul(L"\u00D7"), div(L"\u00F7");
    wxString pow(L"^");
}
namespace unary {
    wxString sqrt(L"\u221A");
    wxString sin(L"sin"), cos(L"cos"), tan(L"tan");
    wxString arcsin(L"arcsin"), arccos(L"arccos"), arctan(L"tan");
}
namespace constant {
    wxString pi(L"\u03C0");
    wxString light_speed(L"c");
    wxString avogadro_number(L"N\u1D00");
    wxString atomic_mass_unit(L"u");
    wxString planck(L"h");
    wxString gas(L"R");
    wxString gravity_acceleration(L"g");
    wxString golden_ratio(L"\u03D5");
}

namespace calc
{
    std::map < wxString, std::function<long double(long double, long double)> > binary
    {
        {binary::add, [](long double a, long double b) { return a + b; }},
        {binary::sub, [](long double a, long double b) { return a - b; }},
        {binary::mul, [](long double a, long double b) { return a * b; }},
        {binary::div, [](long double a, long double b) { return a / b; }},
        {binary::pow, [](long double a, long double b) { return pow(a, b); }}
    };

    std::map < wxString, std::function<long double(long double)> > unary
    {
        {unary::sqrt, [](long double n) { return sqrt(n); }},
        {unary::sin, [](long double n) { return sin(n * 3.14159265359 / 180); }},       //trasformazione da rad a gradi
        {unary::cos, [](long double n) { return cos(n * 3.14159265359 / 180); }},
        {unary::tan, [](long double n) { return tan(n * 3.14159265359 / 180); }},
        {unary::arcsin, [](long double n) { return asin(n) * 180 / 3.14159265359; } },  //trasformazione da rad a gradi
        {unary::arccos, [](long double n) { return acos(n) * 180 / 3.14159265359; } },
        {unary::arctan, [](long double n) { return atan(n) * 180 / 3.14159265359; } }
    };

    std::map < wxString, long double > constant
    {
        {constant::pi, 3.14159265359},
        {constant::light_speed, 299792458},
        {constant::avogadro_number, 6.02214086 * pow(10, 23)},
        {constant::atomic_mass_unit, 1.67 * pow(10, -27)},
        {constant::planck, 6.626 * pow(10, -34)},
        {constant::gas, 8.314},
        {constant::gravity_acceleration, 9.80665},
        {constant::golden_ratio, 1.6180339887}
    };
}


inline bool isBinary(wxString needle)
{
    return (calc::binary.count(needle));
}

inline bool isUnary(wxString needle)
{
    return (calc::unary.count(needle));
}

inline bool isConstant(wxString needle)
{
    return (calc::constant.count(needle));
}

EDIT

I followed some advice and modified my code like so (still having the issue):

ops.h

#pragma once
#include "wx/wx.h"
#include <cmath>
#include <map>

namespace binary {
    extern const wxString add, sub, mul, div;
}
namespace unary {
    extern const wxString sqrt, sin, cos, tan, arcsin, arccos, arctan;
}
namespace constant {
    extern const wxString pi, light_speed, avogadro_number, atomic_mass_unit, planck, gas, gravity_acceleration, golden_ratio;
}

namespace calc
{
    extern const std::map < wxString, std::function<long double(long double, long double)> > binary;
    extern const std::map < wxString, std::function<long double(long double)> > unary;
    extern const std::map < wxString, long double > constant;
}

bool isBinary(wxString needle);
bool isUnary(wxString needle);
bool isConstant(wxString needle);

ops.cpp

#include "ops.h"

namespace binary {
    const wxString add(L"+"), sub(L"-");
    const wxString mul(L"\u00D7"), div(L"\u00F7");
    const wxString pow(L"^");
}
namespace unary {
    const wxString sqrt(L"\u221A");
    const wxString sin(L"sin"), cos(L"cos"), tan(L"tan");
    const wxString arcsin(L"arcsin"), arccos(L"arccos"), arctan(L"tan");
}
namespace constant {
    const wxString pi(L"\u03C0");
    const wxString light_speed(L"c");
    const wxString avogadro_number(L"N\u1D00");
    const wxString atomic_mass_unit(L"u");
    const wxString planck(L"h");
    const wxString gas(L"R");
    const wxString gravity_acceleration(L"g");
    const wxString golden_ratio(L"\u03D5");
}

namespace calc
{
    const std::map < wxString, std::function<long double(long double, long double)> > binary
    {
        {binary::add, [](long double a, long double b) { return a + b; }},
        {binary::sub, [](long double a, long double b) { return a - b; }},
        {binary::mul, [](long double a, long double b) { return a * b; }},
        {binary::div, [](long double a, long double b) { return a / b; }},
        {binary::pow, [](long double a, long double b) { return pow(a, b); }}
    };

    const std::map < wxString, std::function<long double(long double)> > unary
    {
        {unary::sqrt, [](long double n) { return sqrt(n); }},
        {unary::sin, [](long double n) { return sin(n * 3.14159265359 / 180); }},       //trasformazione da rad a gradi
        {unary::cos, [](long double n) { return cos(n * 3.14159265359 / 180); }},
        {unary::tan, [](long double n) { return tan(n * 3.14159265359 / 180); }},
        {unary::arcsin, [](long double n) { return asin(n) * 180 / 3.14159265359; } },  //trasformazione da rad a gradi
        {unary::arccos, [](long double n) { return acos(n) * 180 / 3.14159265359; } },
        {unary::arctan, [](long double n) { return atan(n) * 180 / 3.14159265359; } }
    };

    const std::map < wxString, long double > constant
    {
        {constant::pi, 3.14159265359},
        {constant::light_speed, 299792458},
        {constant::avogadro_number, 6.02214086 * pow(10, 23)},
        {constant::atomic_mass_unit, 1.67 * pow(10, -27)},
        {constant::planck, 6.626 * pow(10, -34)},
        {constant::gas, 8.314},
        {constant::gravity_acceleration, 9.80665},
        {constant::golden_ratio, 1.6180339887}
    };
}


bool isBinary(wxString needle)
{
    return (calc::binary.count(needle));
}

bool isUnary(wxString needle)
{
    return (calc::unary.count(needle));
}

bool isConstant(wxString needle)
{
    return (calc::constant.count(needle));
}

EDIT

Another try I made (now just 19 errors):

ops.h

#pragma once
#include "wx/wx.h"
#include <cmath>
#include <map>

namespace binary
{
    extern const wxString add, sub, mul, div, pow;
}

namespace unary
{
    extern const wxString sqrt, sin, cos, tan, arcsin, arccos, arctan;
}

namespace constant
{
    extern const wxString pi, avogadro_number, planck, gas, atomic_mass_unit;
}

namespace calc
{
    extern std::map < wxString, std::function<long double(long double, long double)> > binary;
    extern std::map < wxString, std::function<long double(long double)> > unary;
    extern std::map < wxString, long double > constant;
}

bool isBinary(wxString needle);
bool isUnary(wxString needle);
bool isConstant(wxString needle);

ops.cpp

#include "ops.h"

namespace binary
{
    extern const wxString 
        add(L"+"), 
        sub(L"-"), 
        mul(L"\u00D7"), 
        div(L"\u00F7"), 
        pow(L"^");
}

namespace unary
{
    extern const wxString 
        sqrt(L"\u221A"),
        sin(L"sin"), 
        cos(L"cos"), 
        tan(L"tan"),
        arcsin(L"arcsin"),
        arccos(L"arccos"),
        arctan(L"arctan");
}

namespace constant
{
    extern const wxString
        pi(L"\u03C0"),
        avogadro_number(L"N\u2090"),
        planck(L"h"),
        gas(L"R"),
        atomic_mass_unit(L"u");
}

namespace calc
{
    extern std::map < wxString, std::function<long double(long double, long double)> > binary = {
        {binary::add, [](long double a, long double b) { return a + b; }},
        {binary::sub, [](long double a, long double b) { return a - b; }},
        {binary::mul, [](long double a, long double b) { return a * b; }},
        {binary::div, [](long double a, long double b) { return a / b; }},
        {binary::pow, [](long double a, long double b) { return pow(a, b); }}
    };
    extern std::map < wxString, std::function<long double(long double)> > unary = {
        {unary::sqrt, [](long double n) { return sqrt(n); }}
    };
    extern std::map < wxString, long double > constant = {
        {constant::pi, 3.1415926535}
    };
}

bool isBinary(wxString needle)
{
    return (calc::binary.count(needle));
}

bool isUnary(wxString needle)
{
    return (calc::unary.count(needle));
}

bool isConstant(wxString needle)
{
    return (calc::constant.count(needle));
}

Upvotes: 0

Views: 333

Answers (2)

Lauri Nurmi
Lauri Nurmi

Reputation: 591

The issue is that because you have symbol definitions in a .h file, each of your symbols gets defined in each compilation unit. That is, each symbol is defined in A.cpp, and then again in B.cpp, C.cpp, and so on. In the end you have several symbols with the same name, and that is not allowed.

The solution is to move all those definitions to one single .cpp file, and then declare them in the .h file by using the extern keyword. For example: extern wxString sqrt;.

Also, since you most likely do not intend to modify the value of those symbols, all of them should be const wxString instead of just wxString.

Upvotes: 3

Z With Glasses
Z With Glasses

Reputation: 106

Have you tried..

#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif

I'm only a beginner but I know pragma once != ifndef. Or perhaps something like that in your .cpp.

Upvotes: 0

Related Questions