【问题标题】:C++ linker error with static functions in .hpp-file.hpp 文件中带有静态函数的 C++ 链接器错误
【发布时间】:2013-05-23 15:00:08
【问题描述】:

我正在使用一个开源库,它提供了一个 .hpp 文件,其中定义了几个静态函数,类似于下面的代码。

当我在我的项目中两次包含此文件时,我总是收到一个链接器错误,抱怨重复符号。我很清楚函数被定义了两次,但我不知道如何解决这个问题。我试过标记函数 extern 或 inline 没有成功。

解决这个问题的最佳方法是什么?

#ifndef OPENMVG_ROBUST_ESTIMATOR_ACRANSAC_H_
#define OPENMVG_ROBUST_ESTIMATOR_ACRANSAC_H_

#include <algorithm>
#include <cmath>
#include <iterator>
#include <vector>
#include <limits>
#include <iostream>

#include "openMVG/robust_estimation/rand_sampling.hpp"

namespace openMVG {
namespace robust{

static double logcombi(size_t k, size_t n)
{...}

...

编辑:我忘了说还有模板函数,也就是说我不能使用.h和.cpp文件。这就是他们使用 .hpp 文件的原因。在此页面 (http://www.cplusplus.com/doc/tutorial/templates/) 的底部,它说链接器在这种情况下不应产生错误。我使用 Xcode 作为标准设置的 IDE。显然这里有问题。链接器错误如下所示:

duplicate symbol __ZN7openMVG6robust13UniformSampleEmmPSt6vectorImSaImEE in:
    /Users/chris/Library/Developer/Xcode/DerivedData/SfM_OpenMVG-dgkssozpvorbpphdefdpurfpdaqv/Build/Intermediates/SfM_OpenMVG.build/Debug/SfM_incremental_unified.build/Objects-normal/x86_64/SfMIncrementalEngine.o
    /Users/chris/Library/Developer/Xcode/DerivedData/SfM_OpenMVG-dgkssozpvorbpphdefdpurfpdaqv/Build/Intermediates/SfM_OpenMVG.build/Debug/SfM_incremental_unified.build/Objects-normal/x86_64/computeMatches.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

解决方案:事实证明,我所指的 hpp 文件包含一个文件,该文件定义了一个与原始文件中的一个函数同名的函数,这就是导致链接器的原因错误。我不知道为什么在只包含一次 .hpp 文件时这甚至会起作用。

【问题讨论】:

  • 在询问编译器/链接器错误时,请始终在您的问题中包含实际的错误消息。或者,如果它们太多(数百个),则前几个和最后几个相关的。
  • 我之前也有同样的错误。如果static 并不真正意味着很多。刚刚删除它。

标签: c++ function static linker duplicates


【解决方案1】:

我知道你说过你已经这样做了,但是替换

static double logcombi(size_t k, size_t n)

inline double logcombi(size_t k, size_t n)

并且完全重新编译。

【讨论】:

  • 上传整个东西,明天再看看。总是可以链接 c++ 代码;最终
  • 非常感谢!您可以在此处获取 hpp 文件:github.com/openMVG/openMVG/tree/master/src/openMVG/…(名称为“robust_estimator_ACRansac.hpp”。它包括同一目录中的另一个文件。)就像我说的,只有当我至少包含该文件时才会出现问题另外两个文件。
  • 我发现了问题;请参考我的原帖。
【解决方案2】:

在标题中分发你的库是一件很奇怪的事情。由于您可以访问源代码,我只需创建相应的 cpp 文件,将代码从头文件复制并粘贴到 cpp 文件,然后删除头文件中的函数体。

我还要从头文件中删除静态函数:在您希望在其中找到可导出符号(即公共函数)的文件中具有静态(私有)函数实际上没有多大意义。

最后,您确定那个 hpp 文件中只有函数吗?如果有常数,那同样会有问题。在这种情况下,我会在标头中保留带有 extern 的声明,并将常量移动到 cpp 文件中。

我知道,工作量很大(其实,其实没那么多),但它也是唯一明智的安排方式。

希望这会有所帮助。

【讨论】:

  • 我编辑了我的问题。事实证明,由于模板函数,这无法完成。
【解决方案3】:

据我所知,您在声明它们的地方实现这些功能。这是双重包含错误的原因。到目前为止,您有两种选择:

  1. 按照 Bathsheba 的建议使用“内联”子句。问题是:“内联”只是一个提示。编译器可能会拒绝你内联函数的尝试,即使“forceinline”被问到。看来,您的案例不是内联兼容的,因为它对您没有帮助。
  2. 像往常一样拆分函数 .H + .CPP 对,以便客户端代码包含 .H 文件,然后链接到包含 .CPP 的库

您将文件命名为 .HPP 而不是 .H 的事实与编译器处理它的方式没有任何关系。您可以对文件使用任意扩展名,然后将其作为标题包含在内。因此,这里的命名约定只不过是一种好的编程风格(.H 用于 C/C++ 兼容的头文件,.HPP 仅用于 C++)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-17
    • 1970-01-01
    • 1970-01-01
    • 2018-05-15
    • 1970-01-01
    相关资源
    最近更新 更多