在hello.cpp
文件中,我具有此静态功能。
static void hello()
{
std::cout << "hello" << std::endl;
}
我想从world.h
文件中的其他静态函数中调用此函数,如下所示。
static void world()
{
hello();
std::cout << "world" << std::endl;
}
在这种情况下,最推荐的将hello()
暴露给其他文件的方法是什么?
答案 0 :(得分:1)
如果它在类的Public范围内,我们可以使用范围解析运算符(::)在不初始化对象的情况下访问静态函数。
class Hello
{
public:
static void Hello1()
{
printf("Hello\n");
}
};
然后从其他类(即World.cpp)(请记住包括hello.h文件)。
class World
{
public:
World(){
Hello::Hello1();
std::cout << "World" << std::endl;
}
};
答案 1 :(得分:1)
以这种方式使用的关键字static
使函数的链接“内部”。
这意味着hello()
仅在hello.cpp
中可见,即使您将其声明给其他编译单元也是如此。
例如,以下代码产生链接错误(未解析的外部参考):
hello.cpp:
#include <iostream>
static void hello()
{
std::cout << "hello" << std::endl;
}
hello.h:
#pragma once
void hello(); // OK, it's declared
main.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!
}
因此,按照定义,您不能以这种方式公开您的函数。
现在,如果您从static
删除了hello()
的代码后,声明了函数hello.cpp
并直接在其头文件中实现了该功能:
hello.h:
#pragma once
static void hello()
{
std::cout << "hello" << std::endl;
}
最终,您将拥有与包含此文件的编译单元一样多的功能hello()
。尝试在多个hello.h
文件中包含.cpp
,并从每个文件中获取指向此hello函数的指针。您会看到他们的地址不同:
main.cpp:
#include <iostream>
#include "otherFile.h"
void main()
{
void * pf = hello; // Gives 0x01181810 during the test I'm currently doing while writing
tryWithAnotherCppFile();
}
otherFile.h:
#pragma once
void tryWithAnotherCppFile();
otherFile.cpp:
#include "otherFile.h"
#include "hello.h"
void tryWithAnotherCppFile()
{
void * pf = hello; // Here it gives 0x01181d40, which is different!
}
现在,通过将hello.h
声明为hello()
而不是inline
,以下列方式更改static
:
hello.h:
#pragma once
inline void hello()
{
std::cout << "hello" << std::endl;
}
并重做与上述相同的测试:无论包含hello()
(hello.h
的cpp文件,我现在0x003c13de
的地址都相同现在)。您的函数不再是静态的,它具有外部链接,并且是唯一的并在所有编译单元之间共享。
this tutorial中提供了更多详细信息。 一篇相关的文章,但我建议阅读全文:
当符号具有内部链接时,它将仅在 当前翻译单位。不要将此处可见的术语与 像私人访问权限。这里的可见性意味着链接器将 仅在处理翻译单元时才能使用此符号 在其中声明符号,而不是在以后声明符号(如带有 外部链接)。实际上,这意味着当您声明一个 在头文件中具有内部链接的符号,每次翻译 您在其中包含此文件的单元将获得该文件的唯一副本 符号。