Reputation: 83
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
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
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