C++
Как сделать свою библиотеку C++: заголовок, cpp-файл и сборка
Чтобы сделать свою библиотеку C++, нужно отделить код, который вы хотите переиспользовать, от основной программы. Обычно библиотека состоит из заголовочного файла .h или .hpp, файла реализации .cpp и сборки, которая подключает этот код к приложению
Самый простой путь:
- Создать заголовочный файл с объявлениями.
- Создать
.cppфайл с реализациями. - Подключить заголовок в
main.cpp. - Добавить
.cppфайл библиотеки в сборку. - Позже, если нужно, собрать статическую или динамическую библиотеку.
Минимальная библиотека из двух файлов
Создадим файл math_utils.h:
#pragma once
int add(int a, int b);
int multiply(int a, int b);
Теперь файл math_utils.cpp:
#include "math_utils.h"
int add(int a, int b) {
return a + b;
}
int multiply(int a, int b) {
return a * b;
}
И файл main.cpp:
#include <iostream>
#include "math_utils.h"
int main() {
std::cout << add(2, 3) << "\n";
std::cout << multiply(4, 5) << "\n";
return 0;
}
Собрать можно так:
g++ main.cpp math_utils.cpp -o app
Это уже маленькая библиотечная структура, хотя формально мы пока просто добавляем файл реализации в сборку
Что хранить в h и cpp
В заголовочном файле обычно хранят:
- объявления функций;
- объявления классов;
- константы и типы;
- шаблоны, если они нужны.
В .cpp файле хранят реализации обычных функций и методов:
int add(int a, int b) {
return a + b;
}
Заголовок нужен компилятору, чтобы знать интерфейс. .cpp файл нужен линкеру, чтобы найти реализацию
Собрать статическую библиотеку
На Linux или macOS можно собрать объектный файл и архив:
g++ -c math_utils.cpp -o math_utils.o
ar rcs libmath_utils.a math_utils.o
g++ main.cpp -L. -lmath_utils -o app
Здесь libmath_utils.a — статическая библиотека. При линковке приложение получает нужный код из архива
На Windows подход зависит от компилятора: MSVC использует .lib, MinGW может работать с .a
Вариант через CMake
В реальном проекте удобнее описать библиотеку через CMake:
add_library(math_utils STATIC math_utils.cpp)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE math_utils)
Так сборка становится понятнее: сначала объявляется библиотека, затем приложение, затем связь между ними
Как назвать библиотеку
Название должно отражать назначение:
math_utilsдля математических функций;text_utilsдля работы со строками;file_utilsдля файловых помощников.
Не стоит складывать в одну библиотеку все подряд. Хорошая библиотека имеет понятную область ответственности
Добавить namespace
Чтобы имена вашей библиотеки не конфликтовали с чужим кодом, полезно завернуть функции в пространство имен
math_utils.h:
#pragma once
namespace math_utils {
int add(int a, int b);
int multiply(int a, int b);
}
#include "math_utils.h"
namespace math_utils {
int add(int a, int b) {
return a + b;
}
int multiply(int a, int b) {
return a * b;
}
}
Использование:
std::cout << math_utils::add(2, 3) << "\n";
Так сразу видно, что функция принадлежит вашей библиотеке, а не случайно объявлена где-то в проекте
Что считать публичным API
В заголовочный файл стоит выносить только то, чем должны пользоваться другие файлы. Внутренние вспомогательные функции лучше оставить в .cpp, чтобы не расширять интерфейс библиотеки без необходимости
Простое правило: если функция нужна только внутри библиотеки, не добавляйте ее в .h
Частые ошибки
Подключать cpp через include
Обычно не пишут:
#include "math_utils.cpp"
Подключайте .h, а .cpp добавляйте в сборку
Писать реализации обычных функций в h без необходимости
Если функция не inline и не шаблон, реализация в заголовке может привести к ошибкам повторного определения
Забыть добавить cpp-файл в сборку
Если заголовок подключен, но реализация не участвует в сборке, появится ошибка линковки вроде undefined reference
Короткий вывод
Своя библиотека C++ начинается с разделения интерфейса и реализации: .h содержит объявления, .cpp содержит код. Для маленького проекта можно собрать main.cpp вместе с файлом библиотеки, а для более аккуратного варианта использовать статическую библиотеку или CMake add_library
Связанные материалы:
Что почитать дальше по C++
Если нужен общий маршрут по теме, откройте рубрику C++. Для соседних задач пригодятся эти разборы:
- C++ с нуля: первый файл, переменные и вывод
- Visual Studio Code и C++: как настроить VS Code и запустить первый файл
- Как сделать все строки одинакового размера в C++: setw, пробелы и обрезка
- Как сделать интерфейс в приложении на C++: простой вариант с меню