将函数定义放入头文件中

发布于 2024-12-11 03:27:59 字数 221 浏览 0 评论 0原文

如果要将函数定义放在头文件中,似乎有三种不同的解决方案:

  1. 将函数标记为 inline
  2. 将函数标记为 static
  3. 将函数放在匿名命名空间中

(直到最近,我什至都不知道#1。)那么这些解决方案有什么区别,什么时候我应该选择哪个?我处于只有标头的世界中,所以我确实需要标头文件中的定义。

If you want to put function definitions in header files, it appears there are three different solutions:

  1. mark the function as inline
  2. mark the function as static
  3. put the function in an anonymous namespace

(Until recently, I wasn't even aware of #1.) So what are the differences to these solutions, and when I should I prefer which? I'm in header-only world, so I really need the definitions in the header files.

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

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

发布评论

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

评论(4

煞人兵器 2024-12-18 03:27:59

static 和未命名命名空间版本最终是相同的:每个翻译单元将包含它自己的函数版本,这意味着给定一个静态函数 f,指针&f 在每个翻译单元中都会不同,并且程序将包含 N 个不同版本的 f(二进制文件中有更多代码)。

这不是在标头中提供一个函数的正确方法,它将提供N个不同(完全相同)的函数。如果函数包含static局部变量,那么将会有N个不同的static局部变量...

编辑:更明确的是:如果您想要在标头中提供函数的定义而不违反单一定义规则,则正确的方法是使函数内联

The static and unnamed namespace versions end up being the same: each Translation Unit will contain it's own version of the function, and that means that given a static function f, the pointer &f will be different in each translation unit, and the program will contain N different versions of f (more code in the binary).

This is not the right approach to provide a function in a header, it will provide N different (exactly equal) functions. If the function contains static locals then there will be N different static local variables...

EDIT: To make this more explicit: if what you want is to provide the definition of a function in a header without breaking the One Definition Rule, the right approach is to make the function inline.

诠释孤独 2024-12-18 03:27:59

据我所知,头文件中只能定义内联函数和模板函数。

static 函数已被弃用,应使用在未命名命名空间中定义的函数(请参阅 7.3.1.1 p2)。当您在标头中的未命名命名空间中定义函数时,包含该标头(直接或间接)的每个源代码都将具有唯一的定义(请参阅 7.3.1.1 p1)。因此,不应在头文件中的未命名命名空间中定义函数(仅在源文件中)。

引用的标准来自 c++03 标准。

编辑:

下一个示例演示了为什么函数和变量不应定义到标头中的未命名命名空间中:

ops .hpp 包含:

#ifndef OPS_HPP
#define OPS_HPP
namespace
{
int a;
}
#endif

dk1.hpp 包含:

#ifndef DK1_HPP
#define DK1_HPP
void setValue();
void printValue();
#endif

dk1.cpp 包含:

#include "dk1.hpp"
#include "ops.hpp"
#include <iostream>

void setValue()
{
    a=5;
}
void printValue()
{
    std::cout<<a<<std::endl;
}

dk.cpp 包含:

#include "dk1.hpp"
#include "ops.hpp"
#include <iostream>

int main()
{
    // set and print a
    setValue();
    printValue();

    // set and print it again
    a = 22;
    std::cout<<a<<std::endl;

    // print it again
    printValue();
}

像这样编译:

g++ -ansi -pedantic -Wall -Wextra dk.cpp dk1.cpp

并且输出 :

5
22
5

ops 变量 a 对于源文件 dk1.cppdk.cpp 是不同的

As far as I know, only inline and template functions can be defined in header files.

static functions are deprecated, and functions defined in an unnamed namespace should be used instead (see 7.3.1.1 p2). When you define a function in an unnamed namespace in a header, then every source code including that header (directly or indirectly) will have an unique definition (see 7.3.1.1 p1). Therefore, functions should not be defined in the unnamed namespace in header files (only in source files).

The standard referenced are from the c++03 standard.

EDIT:

Next example demonstrates why functions and variables shouldn't be defined into unnamed namespace in headers :

ops.hpp contains:

#ifndef OPS_HPP
#define OPS_HPP
namespace
{
int a;
}
#endif

dk1.hpp contains:

#ifndef DK1_HPP
#define DK1_HPP
void setValue();
void printValue();
#endif

dk1.cpp contains:

#include "dk1.hpp"
#include "ops.hpp"
#include <iostream>

void setValue()
{
    a=5;
}
void printValue()
{
    std::cout<<a<<std::endl;
}

dk.cpp contains :

#include "dk1.hpp"
#include "ops.hpp"
#include <iostream>

int main()
{
    // set and print a
    setValue();
    printValue();

    // set and print it again
    a = 22;
    std::cout<<a<<std::endl;

    // print it again
    printValue();
}

Compile like this:

g++ -ansi -pedantic -Wall -Wextra dk.cpp dk1.cpp

and the output :

5
22
5

ops the variable a is different for the source file dk1.cpp and dk.cpp

ㄟ。诗瑗 2024-12-18 03:27:59

static 函数(相当于匿名命名空间)为每个 TU 接收不同的副本。如果函数是可重入的,则这基本上是相同的(某些编译器可能具有汇编级差异),但如果不是,则每个 TU 都会有不同的静态数据。内联函数是折叠的——也就是说,它们对于每个 TU 仅有一份静态数据副本。

static functions (equivalent to anonymous namespace) receive different copies for each TU. If the function is re-entrant this is basically identical (some compilers might have assembly-level differences) but if it isn't then it will have different static data for each TU. Inline functions are folded- that is, they have only one copy of static data for every TU.

静待花开 2024-12-18 03:27:59

您可以考虑将方法包装在类中而不是命名空间中。将这些方法声明为静态方法并删除类的构造函数以强调这不是要实例化的对象。

struct FooNamespace
{
    FooNamespace() = delete;

    static FooMethod1() {
        ...
    }
    static FooMethod2() {
        ...
    }

};

您将获得与属于仅具有单个实现的命名空间相同的一般行为。

You could consider wrapping the methods in a class instead of a namespace. Declare these methods as static and delete the constructor of the class to reinforce that this is not an object to be instantiated.

struct FooNamespace
{
    FooNamespace() = delete;

    static FooMethod1() {
        ...
    }
    static FooMethod2() {
        ...
    }

};

You get the same general behavior as it belonging to a namespace with only a single implementation.

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