Visual Studio 中的链接器错误

Linker errors in Visual Studio

我正在编写一个 C++ wxWidgets 计算器应用程序。我有这个头文件,我在其中声明我的应用程序支持的各种操作和常量。当我尝试编译时,出现 258 LNK2005 错误,例如:

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

此文件中的所有内容依此类推。每次在其他文件中引用这些对象之一时似乎都会出错。

#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));
}

编辑

我听从了一些建议并像这样修改了我的代码(仍然有问题):

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));
}

编辑

我的另一个尝试(现在只有 19 个错误):

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));
}

你试过了吗..

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

我只是个初学者,但我知道 pragma once != ifndef。 或者你的 .cpp 中可能有类似的东西。

问题是因为您在 .h 文件中有符号定义,所以您的每个符号都在每个编译单元中定义。即每个符号在A.cpp中定义,然后又在B.cppC.cpp中定义,依此类推。最后你有几个同名的符号,这是不允许的。

解决方案是将所有这些定义移动到一个 .cpp 文件中,然后使用 extern 关键字在 .h 文件中声明它们。例如:extern wxString sqrt;.

此外,由于您很可能不打算修改这些符号的值,因此所有符号都应该是 const wxString 而不仅仅是 wxString.