【问题标题】:Duplicate symbol for struct in header guarded file [duplicate]标头保护文件中结构的重复符号[重复]
【发布时间】:2018-08-11 00:13:47
【问题描述】:

我遇到了 c++ 链接问题。我正在尝试为所有其他要使用的文件定义一个 Point2D 结构。在这里。

#ifndef Point2D_h
#define Point2D_h

#include <iostream>

struct Point2D {
    float x;
    float y;


    Point2D(float x, float y) : x(x), y(y) {}

    Point2D() : x(0), y(0) {}

    Point2D operator+(const Point2D& a) const {
        return Point2D(a.x + x, a.y + y);
    }

    ….
};

std::ostream& operator<<(std::ostream& os, const Point2D& m) {
    return os << "(" << m.x << ", " << m.y << ")";
}

#endif /* Point2D_h */

唯一的问题是我在尝试构建时收到重复符号 Point2D 错误。我不确定为什么 Point2D 会是一个重复的符号,因为它是受标头保护的

这是我的所有其他文件,无论它们是否受标头保护,是否使用 Point2D,当然还有它们的导入:

Global.h(标头保护)

#include <stdio.h>
#define MAX 9000

引擎核心(标头保护)

#import "Global.h"
#import "Tests/EngineTests.hpp"
#import "Engine/Engine.hpp"
#import "Particle/Particle.hpp"

Tests.cpp(使用 Point2D)

#include "EngineTests.hpp"
#include <iostream>
#include "../Engine/Engine.hpp"

测试.h

#include "Global.h"

Engine.cpp

#include "Engine.hpp"
#include <iostream>

Engine.hpp(标头保护)

#include "Global.h"
#include "../Particle/ParticleManager.hpp"

粒子.cpp

#include "Particle.hpp"
#include <iostream>

Particle.h(标题受保护,使用 Point2D)

#include "Global.h"
#include "../Math/Point.h"

粒子管理器.cpp

#include "ParticleManager.hpp"
#include <iostream>

ParticleManager.h(头文件保护)

#include <stdio.h>
#include "Global.h"
#include "Particle.hpp"

链接器说以下内容

duplicate symbol __ZlsRNSt3__113basic_ostreamIcNS_11char_traitsIcEEEERK7Point2D in:
    …/arm64/Particle.o
    …larm64/Engine.o
duplicate symbol __ZlsRNSt3__113basic_ostreamIcNS_11char_traitsIcEEEERK7Point2D in:
    …/Particle.o
    …/arm64/EngineTests.o
duplicate symbol __ZlsRNSt3__113basic_ostreamIcNS_11char_traitsIcEEEERK7Point2D in:
    …/arm64/Particle.o
    …/ParticleManager.o
ld: 3 duplicate symbols for architecture arm64

【问题讨论】:

  • 该错误是针对您的operator&lt;&lt; 函数的。不要在头文件中定义函数。 (此外,标头保护不能防止链接器错误。)
  • 标头保护阻止标头在一个编译单元(或 cpp 文件,如果您愿意)中多次包含,它们不会阻止在编译其他文件时包含标头。跨度>
  • 一种解决方法是在operator&lt;&lt;的定义中添加关键字inline。另一种解决方法是在标头中声明它,并在 .cpp 文件中提供定义。

标签: c++


【解决方案1】:

短期解决方案:对头文件中定义的函数使用 inline 关键字

inline Point2D operator+(const Point2D& a) const {
    return Point2D(a.x + x, a.y + y);
}

inline std::ostream& operator<<(std::ostream& os, const Point2D& m) {
    return os << "(" << m.x << ", " << m.y << ")";
}

长期:除非是可测量的性能下降,否则不要内联任何代码。 (我的团队禁止使用头文件中的代码)。有你的头文件如下:

#ifndef Point2D_h
#define Point2D_h

#include <iostream>
struct Point2D {
    float x;
    float y;

    Point2D(float x, float y);    
    Point2D();

    Point2D operator+(const Point2D& a) const;

    ….
};

std::ostream& operator<<(std::ostream& os, const Point2D& m);

以及对应的Point2d.cpp文件:

Point2D::Point2D(float x, float y) : x(x), y(y) {}

Point2D::Point2D() : x(0), y(0) {}

Point2D::Point2D operator+(const Point2D& a) const {
    return Point2D(a.x + x, a.y + y);
}

std::ostream& operator<<(std::ostream& os, const Point2D& m) {
    return os << "(" << m.x << ", " << m.y << ")";
}

【讨论】:

  • 我会切换什么是“长期”和什么是“短期”。例如。单独编译仍然缺乏对浏览代码的良好工具支持,使用这种结构的库仍然是 PITA。
猜你喜欢
  • 2013-07-29
  • 1970-01-01
  • 1970-01-01
  • 2012-11-07
  • 1970-01-01
  • 2018-02-22
  • 2013-05-26
  • 1970-01-01
相关资源
最近更新 更多