我开始学习C ++,并且从我的IDE(CodeBlocks)中得到了这个编译错误。我不明白为什么会这样。
|2|multiple definition of `parser::parseFile()'
|2|first defined here|
我不知道这是怎么发生的。这是我的整个代码库。
main.cpp
#include "parser/parser.cpp"
int main()
{
return 0;
}
parser/parser.cpp
namespace parser {
void parseFile() {
}
}
答案 0 :(得分:4)
假设你编译了main.cpp
和parser/parse.cpp
,你显然有parser::parseFile()
的两个定义:#include
指令只会被指定文件的内容所取代(你可以在编译器中使用-E
标志来查看结果。)
你可能想在头文件中声明 parser::parseFile()
(通常带有后缀.h
或.hpp
或类似的东西即):
// file: parser/parser.hpp
#ifndef INCLUDED_PARSER_PARSER
#define INCLUDED_PARSER_PARSER
namespace parser {
void parseFile();
}
#endif
...并将此头文件包含在两个翻译单元中。
答案 1 :(得分:1)
您的计划违反了One Definition Rule (also known as ODR)。
简而言之,parser::parseFile
函数已在两个.cpp
文件中定义,因为在编译器级别上,#include <header.h>
只是意味着替换整个文件内容。
但问题的解决方案取决于您的实际程序。如果要解决类定义的ODR规则,可以执行以下任一操作:
1)在标题的开头添加#pragma once
。虽然得到了所有主要编译器的支持,但这并不是标准化的方法,可以防止双重包括标题。
2)添加包含警卫:
#ifndef MY_HEADER_GUARD
#define MY_HEADER_GUARD
// your header contents go here
#endif
如果要解决函数和数据变量的ODR问题,上述方法将无效,因为您仍可以在不同的.cpp
文件中多次定义它们。
为此,您仍有2个选项:
1)在外面某处定义你的函数,即在某个.cpp
文件中,只将其声明留在标题中:
// header.h
namespace parser {
void func();
}
// file.cpp
void parser::func() { ... }
2)将你的函数声明为 inline ,因为内联函数允许C ++标准有多个定义(但是,它们必须严格相同,直到lexem级别):
// header.h
namespace parser {
inline void func() { ... }
}
总结一下,我强烈建议您通过保护标题免于双重包含和来确保您的功能是内联的,或者在.cpp
文件中定义。对于后者,如果您的函数实现发生更改,则不必重新编译包含标题的所有文件,而只需重新编译具有functon定义的文件。
答案 2 :(得分:0)
头文件通常用于将类和函数声明与其实现分开。
在 Code :: Blocks 中,您可以通过右键单击项目名称来添加标题文件 - &gt; &#39;添加文件&#39; - &gt; 使用 .h 扩展名创建新文件。按照良好实践,您还应该创建一个 .cpp 文件,其中包含编写实现的相同名称。
如前所述,在您的标题文件中,您可以先写一个include guard,然后输入 include (如果有的话),还可以功能声明。在您的&#39; parser.cpp&#39; &amp; &#39; main.cpp&#39; 您必须#include "parser.h"
,因为文件依赖于彼此。