4

我第一次在一个项目中使用多个 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(); }

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

4

3 回答 3

5

您有两种选择来解决这个多重定义问题:将方法标记为内联,或将定义放在 .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允许您在头文件中定义一个非成员函数,而不会破坏一个定义规则。

于 2013-07-15T05:07:35.817 回答
3

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

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

您需要:

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

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

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

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

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(); }
于 2013-07-15T05:20:43.097 回答
1

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

  • 添加inline到定义或
  • 从标头中删除函数体并将其放入源文件的 1 个(并且只有 1 个)中。
于 2013-07-15T04:51:43.213 回答