C какой наилучший способ сделать некоторые функции внутри исходного файла закрытыми?

#c #compilation #header #namespaces #private

#c #Сборник #заголовок #пространства имен #Частное #c

Вопрос:

 // myclass.h
#pragma once
void publicFunction();

//------
// myclass.cpp
#include "myclass.h"
#include <iostream>

void privateFunction() {
    std::cout << "Hello worldn";
}

void publicFunction() {
    privateFunction();
}

//-------
// main.cpp
#include "myclass.h"
#include <iostream>

void privateFunction() {
    std::cout << "Hello mainn";
}

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 worldn";
}
//---
using namespace MyClass;

void publicFunction() {
    privateFunction();
}
  

Правильный ли это способ решить эту проблему? Я чувствую, что это может вызвать некоторые проблемы позже, но я не знаю, как правильно.

Ответ №1:

Если вы объявляете функцию в заголовочном файле, то для начала это не private так. Если privateFunction предполагается, что это деталь реализации, рассмотрите возможность объявления ее только в блоке перевода. Для этого у вас есть два распространенных варианта.

  1. Используйте anonymous namespace в файле реализации.

     namespace {
      void privateFunction() {
        std::cout << "Hello worldn";
      }
    }
      

    Таким образом, вы можете вызывать privateFunction() из publicFunction , по-прежнему защищая любое использование privateFunction извне модуля компиляции.

  2. Создайте функцию static внутри блока перевода.

     static void privateFunction() {
        std::cout << "Hello worldn";
    }
      

    который имеет тот же эффект, что и 1.

Выбор между 1. и 2. в основном зависит от вкуса. Если вы хотите упорядочить определения функций таким образом, чтобы вызываемые функции отображались под вызывающими, выберите 2., как 1. применяет определения функций в момент их объявления.

Обратите внимание, что недостатком такой изоляции является ограниченная возможность написания специальных модульных тестов для вспомогательных функций, поскольку вы не можете связать их с теми, что «извне».

Ответ №2:

Решение 1:

Объявите функцию static .

 static void privateFunction() { ... }
  

Решение 2:

Объявите функцию внутри неназванного пространства имен.

 namespace {
    void privateFunction() { ... }
}
  

В обоих случаях функция получает внутреннюю привязку, что означает, что она видна только внутри единицы перевода.

Ответ №3:

Другой способ — использовать class, а внутри класса вы можете использовать «private» и «public» для разделения ваших функций и переменных.