C++

Как сделать свою библиотеку C++: заголовок, cpp-файл и сборка

Чтобы сделать свою библиотеку C++, нужно отделить код, который вы хотите переиспользовать, от основной программы. Обычно библиотека состоит из заголовочного файла .h или .hpp, файла реализации .cpp и сборки, которая подключает этот код к приложению

Самый простой путь:

  1. Создать заголовочный файл с объявлениями.
  2. Создать .cpp файл с реализациями.
  3. Подключить заголовок в main.cpp.
  4. Добавить .cpp файл библиотеки в сборку.
  5. Позже, если нужно, собрать статическую или динамическую библиотеку.

Минимальная библиотека из двух файлов

Создадим файл 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++. Для соседних задач пригодятся эти разборы:

Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные

Настройки cookie

0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x