【问题标题】:Multple c++ files causes "multiple definition" error?多个 c++ 文件导致“多重定义”错误?
【发布时间】:2013-07-12 21:18:19
【问题描述】:

我第一次在一个项目中使用多个 C++ 文件。两者都需要包含一个受保护的 (#ifndef) 头文件。但是,当我这样做时,会出现多重定义错误。

我有两个直接调用标头的 .cpp 文件,一个间接调用(另一个包含它),然后是另外两个包含它的头文件。

那么我需要做些什么来消除错误?

错误:

obj\Debug\main.o||在函数Z14sortLibQtyTest4BookS_':| [PATH]\miscFuncs.h|16|multiple definition ofsortLibQtyTest(Book, Book)'

代码:

bool sortLibQtyTest(Book a, Book b){ return a.getQty() > b.getQty(); }

应该提到,这不是唯一给我带来问题的功能,可能有十多个,有些不是那么简短和甜蜜。此外,多个文件中需要这些函数。

【问题讨论】:

  • 如果该函数不是类的一部分并在标头中定义,则它应该是内联的。
  • 标记方法inline,或将定义放入.cpp文件中。
  • 查看附加信息。本来应该说的。
  • 这两条信息都没有改变任何东西。

标签: c++ multiple-definition-error


【解决方案1】:

您有两种选择来解决这个多重定义问题:将方法标记为内联,或将定义放在 .cpp 文件中。

1) 将方法标记为内联:

// Foo.h

inline bool foo(int i) { return i = 42; }

2) 将定义放入.cpp 文件中:

// Foo.h

inline bool foo(int i); // declaration

// Foo.cpp
bool foo(int i) { return i = 42; } // definition

在第一种情况下,编译器是否实际内联该方法在这里无关紧要:inline 允许您在头文件中定义非成员函数,而不会破坏一个定义规则。

【讨论】:

  • 对于其他阅读本文的人来说,这是最简洁明了的答案。为了更好地理解,请阅读其他帖子中的 cmets。
【解决方案2】:

“.cpp”和“.h”后缀在很大程度上是约定俗成的问题。就编译器而言,一行代码来自哪里是无关紧要的。当您将该函数#include 到您的 .cpp 文件中时,您就是在该 .cpp 文件中实现该函数。

因此,当编译器完成并要求链接器将两个 cpp 文件中的代码组合在一起时,它会发现冲突:两个具有相同名称和指纹的函数(参数和返回)。这是一个错误。

您需要:

一个。将实现放在一个源文件中,并在标题中留下原型声明

// .h
extern bool sortLibQtyTest(Book a, Book b);

// file1.cpp
bool sortLibQtyTest(Book a, Book b) { /* implementation */ }

b.将函数标记为内联:当你调用函数时,编译器会根据需要插入函数体的副本,这可能是一种浪费,但通常编译器可以找出有效的方法。

inline bool sortLibQtyTest(Book a, Book b) { return a.getQty() < b.getQty(); }

c。将函数标记为“静态”,这告诉编译器为包含它的每个源文件创建函数的副本,但不将其公开给链接器。如果某些源文件在不使用该函数的情况下包含头文件,则编译器必须检测到并删除它 - 并非所有编译器/优化级别都这样做,因此可能会加倍浪费。

static bool sortLibQtyTest(Book a, Book b) {return a.getQty() < b.getQty(); }

d。避免c的缺点,将其标记为静态内联

static inline bool sortLibQtyTest(Book a, Book b) { return a.getQty() < b.getQty(); }

【讨论】:

    【解决方案3】:

    如果您在“CODE”之后引用的行在头文件中,您可以:

    • 在定义中添加inline
    • 从标头中删除函数体并将其放入 1 个(并且只有 1 个)源文件中。

    【讨论】:

    • @David inline 说明符不强制内联。如果它不能内联它,那么它不会。那么它的唯一目的就是避免出现多个定义错误。
    • @David 你只需要选择这两个选项之一。听起来第二种选择更好。
    • @David 这取决于实现。并非所有编译器都是相同的,同样,如果您需要,编译器也有某些方法可以强制内联。 inline 关键字本身不会这样做,因为它是一个提示。
    • @David 正如我所说,我认为第二种选择,即将函数定义放在 .cpp 文件中,如果你的函数不是微不足道的,可能会更好。但两种解决方案都可以解决问题。
    • 您绝对应该阅读有关 C++ 基础知识的书(或任何适当的在线资源),包括声明和定义之间的区别以及使用头文件和源文件的方式。 “常用方法”是在头文件中声明(没有函数体)并在关联的源文件中定义(函数体)。
    猜你喜欢
    • 1970-01-01
    • 2015-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-13
    • 2019-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多