根据评论
考虑以下代码分解为文件// parent.h
#pragma once
class parent{
public:
virtual ~parent() =0;
};
parent::~parent(){}
// child.h
#pragma once
#include "parent.h"
class child: public parent{
public:
~child();
};
// child.cpp
#include "child.h"
child::~child(){}
// main.cpp
#include "parent.h"
#include "child.h"
int main(){}
使用g++ main.cpp child.cpp
编译上述代码会出现以下错误:
duplicate symbol __ZN6parentD2Ev in:
/var/folders/cr/zst9m2t112929f2wg4pkckjc0000gn/T/main-856b8b.o
/var/folders/cr/zst9m2t112929f2wg4pkckjc0000gn/T/child-18a967.o
duplicate symbol __ZN6parentD1Ev in:
/var/folders/cr/zst9m2t112929f2wg4pkckjc0000gn/T/main-856b8b.o
/var/folders/cr/zst9m2t112929f2wg4pkckjc0000gn/T/child-18a967.o
duplicate symbol __ZN6parentD0Ev in:
/var/folders/cr/zst9m2t112929f2wg4pkckjc0000gn/T/main-856b8b.o
/var/folders/cr/zst9m2t112929f2wg4pkckjc0000gn/T/child-18a967.o
ld: 3 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
然而,在一个文件中运行这个非常相似的程序编译并运行良好
class parent{
public:
virtual ~parent() =0;
};
parent::~parent(){}
class child: public parent{
public:
~child();
};
child::~child(){}
int main(){}
这是为什么?如何将第二个单个文件程序分解为多个文件程序而不会导致编译错误,错误是什么以及导致它的原因是什么?
感谢
答案 0 :(得分:4)
正如链接器所说,你有parent
的析构函数的多个定义。换句话说,这个定义:
parent::~parent(){}
同时出现在main.cpp
和child.cpp
。
要解决此问题,您可以:
将定义移动到自己的parent.cpp
(就像您为child.cpp
所做的那样),以便整个程序中只有一个:
parent::~parent(){}
或者将其保留在标题中,但请将其标记为inline,以便允许多个(相同的)定义:
inline parent::~parent(){}
如果该函数不是纯虚函数(= 0
),您还可以选择在声明它时直接定义它:
struct A
{
virtual f() {};
}
// No need for f::f() {}
答案 1 :(得分:1)
错误是在类定义之外的标头中定义的父析构函数。
Child.cpp和Main.cpp是两个不同的翻译单元,都获得该析构函数定义的副本。
答案 2 :(得分:1)
您的问题似乎是 parent.h 中的这一行:
parent::~parent(){}
定义一个函数,它在包含 parent.h 的每个文件中定义。请仔细阅读错误消息,您应该看到它。
要修复,一种方法是在 parent.h 中内联函数定义,例如:
inline parent::~parent(){}
如果方法不是纯虚拟的,你可以在类中移动定义,然后它将隐式内联(但在这种情况下不会起作用)。然后你也可以将它移动到 .cpp 文件,这样它只会转到一个 .o 文件,你可以避免重复的符号。