问题描述
// myclass.h
#pragma once
void publicFunction();
//------
// myclass.cpp
#include "myclass.h"
#include <iostream>
void privateFunction() {
std::cout << "Hello world\n";
}
void publicFunction() {
privateFunction();
}
//-------
// main.cpp
#include "myclass.h"
#include <iostream>
void privateFunction() {
std::cout << "Hello main\n";
}
int main()
{
privateFunction();
}
以上程序将无法编译(privateFunction(void) already defined in myclass.obj
)。解决此问题的一种方法是在源文件中定义一个namespace
:
#include "myclass.h"
#include <iostream>
namespace MyClass
{
void privateFunction();
// add a bunch other private functions here
}
void MyClass::privateFunction() {
std::cout << "Hello world\n";
}
//---
using namespace MyClass;
void publicFunction() {
privateFunction();
}
这是解决此问题的正确方法吗?我觉得以后可能会引起一些问题,但是我不知道正确的方法是什么。
解决方法
如果在头文件中声明一个函数,则开头不是private
。如果privateFunction
应该是实现细节,请考虑仅在翻译单元中声明它。为此,您有两个常用选项。
-
在实现文件中使用匿名
namespace
。namespace { void privateFunction() { std::cout << "Hello world\n"; } }
通过这种方式,您可以从
privateFunction()
调用publicFunction
,同时仍然可以防止在编译单元外部使用privateFunction
。 -
在翻译单元中使用功能
static
。static void privateFunction() { std::cout << "Hello world\n"; }
与1具有相同的作用。
在1.和2.之间进行选择主要取决于品味。如果您希望对函数定义进行排序,以使被调用函数出现在调用函数的下方,请选择2.,因为1.在声明时强制执行函数定义。
请注意,这种隔离的缺点是无法为辅助功能编写特定的单元测试,因为您无法与“外部”的功能进行链接。
,解决方案1 :
声明函数static
。
static void privateFunction() { ... }
解决方案2 :
在未命名的命名空间中声明函数。
namespace {
void privateFunction() { ... }
}
在这两种情况下,该函数均具有内部链接,这意味着它仅在翻译单元中可见。
,另一种方法是使用类,并且可以在类内部使用“私有”和“公共”来分隔函数和变量。