如何将cpp文件中的静态函数暴露给其他文件

Zac*_*Lee 4 c++ static function

hello.cpp文件中,我有这个静态函数。

static void hello()
{
    std::cout << "hello" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

我想从world.h文件中的其他静态函数调用这个函数,如下所示。

static void world()
{
    hello();
    std::cout << "world" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,最推荐的公开hello()其他文件的方法是什么?

Shl*_*blu 7

以这种方式使用,关键字static使函数的链接成为“内部”。即使您将其声明给其他编译单元,该方法hello()也仅在 中可见。hello.cpp

例如,下面的代码会产生链接错误(无法解析的外部引用):

你好.cpp:

#include <iostream>

static void hello()
{
    std::cout << "hello" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

你好.h:

#pragma once

void hello(); // OK, it's declared
Run Code Online (Sandbox Code Playgroud)

主要.cpp:

#include "hello.h"

void main()
{
    hello(); // But ouch, it's not resolved! The linker can't access to the code you wrote in hello.cpp due to the fact hello() is static!
}
Run Code Online (Sandbox Code Playgroud)

因此,根据定义,您不能以这种方式公开您的函数。

现在,如果您在从 中static删除 的hello()代码后声明您的函数并直接在其头文件中实现它hello.cpp

你好.h:

#pragma once

static void hello() 
{
    std::cout << "hello" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

您最终将获得与hello()包含此文件的编译单元一样多的函数。尝试包含hello.h在多个.cpp文件中,并从每个文件中获取指向此 hello 函数的指针。您会看到它们的地址不同:

主要.cpp:

#include <iostream>
#include "otherFile.h"

void main()
{
    void * pf = hello; // Gives 0x01181810 during the test I'm currently doing while writing

    tryWithAnotherCppFile();
}
Run Code Online (Sandbox Code Playgroud)

其他文件.h:

#pragma once

void tryWithAnotherCppFile();
Run Code Online (Sandbox Code Playgroud)

其他文件.cpp:

#include "otherFile.h"
#include "hello.h"

void tryWithAnotherCppFile()
{
    void * pf = hello; // Here it gives 0x01181d40, which is different!
}
Run Code Online (Sandbox Code Playgroud)

现在,通过声明as而不是 来更改hello.h以下方式:hello()inlinestatic

你好.h:

#pragma once

inline void hello() 
{
    std::cout << "hello" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

并重做与上面相同的测试:您将看到,hello()无论包含哪个 cpp 文件, 的地址现在都是相同的hello.h0x003c13de就我而言,现在)。您的函数不再是静态的,它具有外部链接,并且是唯一的并在所有编译单元之间共享。

本教程提供了更多详细信息。一篇相关的文章,但我建议阅读整篇文章:

当符号具有内部链接时,它仅在当前翻译单元内可见。不要将此处可见的术语与私有等访问权限混淆。这里的可见性意味着链接器只能在处理声明该符号的翻译单元时使用该符号,而不能在以后使用该符号(与具有外部链接的符号一样)。实际上,这意味着当您在头文件中声明一个符号具有内部链接时,包含该文件的每个翻译单元都将获得该符号自己的唯一副本。