C++ 中函数已定义错误

发布于 2024-11-28 14:13:28 字数 459 浏览 1 评论 0原文

我有一个名为“SimpleFunctions.h”的文件,定义如下:

#ifndef SIMPLEFUNCTIONS_H
#define SIMPLEFUNCTIONS_H

namespace my_namespace {

double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); }
float round(float r) { return round((double)r); }

}

#endif // SIMPLEFUNCTIONS_H

该文件以前仅包含在一个文件中,并且工作正常。

现在,今天我已将其包含在第二个文件中,但它不再起作用。在链接时,它告诉我该函数已在“firstfile.obj”中定义。

但是,由于我使用的是包含防护,因此我希望函数仅定义一次,或者我是否遗漏了某些内容?

I have a file called "SimpleFunctions.h" defined as follow:

#ifndef SIMPLEFUNCTIONS_H
#define SIMPLEFUNCTIONS_H

namespace my_namespace {

double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); }
float round(float r) { return round((double)r); }

}

#endif // SIMPLEFUNCTIONS_H

This file was previously included in only one file and it was working fine.

Now today I have included it in a second file and it no longer works. At link time, it tells me that the function is already defined in "firstfile.obj".

However, since I am using include guards, I would expect the functions to be defined only once, or am I missing something?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

糖粟与秋泊 2024-12-05 14:13:28

默认情况下,这些函数具有外部链接。这意味着每个翻译单元都有称为 double round(double r) 和 float round(float r) 的函数,这会导致链接时的名称冲突。

一些可能的解决方案是:

  1. 将函数声明为静态,这意味着内部链接
  2. 内联函数
  3. 将实现从标头移出并放入 ac/c++ 文件中

阅读更多内容:
什么是外部链接和内部链接?

通过这种方式,包含防护可以保护单个翻译单元免于多次包含头文件。这是一个与您在这里看到的不同的问题。

By default, these functions have external linkage. That means each translation unit has functions called double round(double r) and float round(float r), which causes a name collision at link time.

Some possible solutions are:

  1. Declare the functions as static, which implies internal linkage
  2. Inline the functions
  3. Move the implementation out of the header and into a c/c++ file

Read more here:
What is external linkage and internal linkage?

By the way, include guards protect a single translation unit from including a header file multiple times. That's a different issue that what you're seeing here.

成熟稳重的好男人 2024-12-05 14:13:28

使用 'inline'

inline double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); }
inline float round(float r) { return round((double)r); }

编译器不一定会内联代码(尽管对于这个短函数来说可能会内联),但链接器不再将 is 视为单独的函数。

注意 - 包含防护会阻止同一包含文件多次包含在同一源文件(严格来说“编译单元”)中,但不会阻止它包含在链接在一起的单独源文件中。这就是为什么您通常在标头中声明它但在 ac 文件中定义该函数的原因

use 'inline'

inline double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); }
inline float round(float r) { return round((double)r); }

The compiler won't necessarily inline the code (although for this short func it may) but the linker doesn't treat is as a separate function anymore.

Note - include guards stop the same include file being included more than once in the same source file (strictly speaking 'compilation unit') it doesn't stop it being included in separate source files that are linked together. That's why you normally declare it in a header but define the function in a c file

鲸落 2024-12-05 14:13:28

解决问题的更好方法是通过模板。如果您要执行以下操作,您的代码将可以正常编译:

template <class T>
T round (T r) {
    return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
}

您的链接器将停止抱怨,并且您将拥有一个满足您所有需求的函数。

该解决方案可以通过类型特征进行改进。请参阅boost::is_floating_point和<一个href="http://www.boost.org/doc/libs/1_49_0/libs/utility/enable_if.html" rel="nofollow">boost::enable_if

A better way to solve the problem is through templates. Your code will compile fine if you were to do something along the lines of:

template <class T>
T round (T r) {
    return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
}

Your linker will stop complaining and you'll have a single function for all of your needs.

This solution can be improved with type traits. See boost::is_floating_point and boost::enable_if

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文