C ++中的多重定义异常

时间:2014-12-21 02:00:49

标签: c++

我开始学习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() {

    }
}

3 个答案:

答案 0 :(得分:4)

假设你编译了main.cppparser/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)

.h (通常)结尾的

头文件通常用于将类和函数声明与其实现分开。

Code :: Blocks 中,您可以通过右键单击项目名称来添加标题文件 - &gt; &#39;添加文件&#39; - &gt; 使用 .h 扩展名创建新文件。按照良好实践,您还应该创建一个 .cpp 文件,其中包含编写实现的相同名称。

如前所述,在您的标题文件中,您可以先写一个include guard,然后输入 include (如果有的话),还可以功能声明。在您的&#39; parser.cpp&#39; &amp; &#39; main.cpp&#39; 您必须#include "parser.h",因为文件依赖于彼此。