我试图编写一个简单的应用程序,允许用户对一组线性方程执行一系列符号操作,并使用"Symbolicc++" library(更具体地说,最新版本3.35)目的
由于我没有多少C ++经验,以前从未真正使用过第三方库,因此我很可能不知道如何正确使用库和我犯了一些愚蠢的错误。
问题是当我尝试编译(和链接)包含多个包含库主标题的文件的程序时,我得到了多个定义错误的批次;错误指的是库文件中定义的函数和类(不是我的文件)。
一个非常简单的例子:假设我们有文件 main.cpp , head.h 和 head.cpp 。内容如下:
main.cpp
------------------
#include <iostream>
#include "head.h"
int main()
{
return 0;
}
head.h
------------------
#ifndef SOMETHING
#define SOMETHING
#include "symbolicc++.h"
#endif
head.cpp
------------------
#include "head.h"
//nothing
当然,真实程序中的文件包含更多内容,但即便如此,尝试使用例如:
来构建程序。g++ -I /path to library's header files/ main.cpp head.cpp
产生数百条错误消息:
/tmp/ccYNzlEF.o: In function `Cloning::Cloning()':
head.cpp:(.text+0x0): multiple definition of `Cloning::Cloning()'
/tmp/ccNWUnnC.o:main.cpp:(.text+0x0): first defined here
其中,例如 Cloning :: Cloning()在 cloning.h 中声明,它是库的头文件之一。
只包含单个文件的程序,包括 symbolicc ++。h 可以正常工作。
我也尝试在Visual Studio 2012上构建这个项目并得到了类似的结果。
不幸的是,我无法找到有关此问题的任何信息,因为我发现的几乎所有材料都涉及用户创建的头文件中的错误(而不是其他人创建的库),所以任何帮助将不胜感激。
答案 0 :(得分:1)
这个库似乎被严重破坏了。它的设计方式,您不能多次包含"symbolicc++.h"
而不违反单一定义规则。
例如,让我们看一下cloning.h
。它使用默认构造函数声明定义Cloning
类:
class Cloning
{
private: int refcount;
void (*free_p)(Cloning*);
// ...
public: Cloning();
// ...
};
稍后, 在头文件 中,它还定义该构造函数:
Cloning::Cloning() : refcount(0), free_p(0) {}
就是这样。直接或间接包含cloning.h
的每个* .cpp文件都将显示在同一函数的定义中。链接器注意到多个定义并放弃。
尝试修改cloning.h
。删除上面的构造函数定义行,并将构造函数定义放入类定义中,使其成为内联函数:
// just to see what's going on...
class Cloning
{
private: int refcount;
void (*free_p)(Cloning*);
// ...
public: Cloning() : refcount(0), free_p(0) {};
// ...
};
这将修复Cloning::Cloning
的错误。但这只是为了解决这个问题;我不建议你这样做。 修复代码将是图书馆作者的工作。
进一步推荐阅读:Why include guards do not prevent multiple function definitions?
以下是一种使用您自己的代码中几行重现相同问题的方法:
<强> head.h:强>
#ifndef SOMETHING
#define SOMETHING
struct Example
{
Example(); // constructor declaration
};
Example::Example() // constructor definition
{
}
#endif
<强> head.cpp:强>
#include "head.h"
//nothing
<强> main.cpp中:强>
#include "head.h"
int main()
{
}
示例链接器错误(取自Visual C ++ 2013):
1>main.obj : error LNK2005: "public: __thiscall Example::Example(void)" (??0Example@@QAE@XZ) already defined in head.obj
1>[...] fatal error LNK1169: one or more multiply defined symbols found
如果您绝对必须使用此库,则必须围绕它构建自己的安全包装。但坦率地说,就是不要。我确信有许多其他库可以解决相同的问题,并且可以根据C ++语言规则和约定实际使用。