#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
предполагается, что это деталь реализации, рассмотрите возможность объявления ее только в блоке перевода. Для этого у вас есть два распространенных варианта.
-
Используйте anonymous
namespace
в файле реализации.namespace { void privateFunction() { std::cout << "Hello worldn"; } }
Таким образом, вы можете вызывать
privateFunction()
изpublicFunction
, по-прежнему защищая любое использованиеprivateFunction
извне модуля компиляции. -
Создайте функцию
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» для разделения ваших функций и переменных.