C++ 将源文件中的某些函数设为私有的最佳方法是什么?

Duk*_* Le 5 c++ namespaces compilation private header

// 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();
}
Run Code Online (Sandbox Code Playgroud)

上述程序将无法编译(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();
}
Run Code Online (Sandbox Code Playgroud)

这是解决这个问题的正确方法吗?我觉得这可能会在以后引起一些问题,但我不知道正确的方法是什么。

lub*_*bgr 6

如果您在头文件中声明一个函数,那么一private开始就不是这样的。如果privateFunction应该是实现细节,请考虑仅在翻译单元中声明它。为此,您有两种常见的选择。

  1. namespace在实现文件中使用匿名。

    namespace {
      void privateFunction() {
        std::cout << "Hello world\n";
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这样,您可以调用privateFunction()from ,同时仍然保护编译单元外部publicFunction的任何使用。privateFunction

  2. static在翻译单元内创建该函数。

    static void privateFunction() {
        std::cout << "Hello world\n";
    }
    
    Run Code Online (Sandbox Code Playgroud)

    与1具有相同的效果。

在 1. 和 2. 之间进行选择主要取决于个人喜好。如果您希望对函数定义进行排序,使被调用函数出现在调用函数下方,请选择 2.,因为 1. 在函数声明点强制执行函数定义。

请注意,这种隔离的缺点是降低了为辅助函数编写特定单元测试的能力,因为您无法链接到来自“外部”的单元测试。


rus*_*tyx 5

解决方案1

声明函数static

static void privateFunction() { ... }
Run Code Online (Sandbox Code Playgroud)

解决方案2

在未命名的命名空间内声明该函数。

namespace {
    void privateFunction() { ... }
}
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,函数都会获得内部链接,这意味着它仅在翻译单元内可见。