Avatar ·

Расширения файлов C++: .cc, .cpp, .cxx, .h — в чем разница и что выбрать?

Всем привет! Я только начал изучать C++ и пишу простые программы в Visual Studio Code. Заметил, что когда создаю новый файл, мне предлагают выбрать из кучи расширений: .cpp, .cc, .cxx, а для заголовочных — .h, .hpp, .hxx. Я привык всегда использовать .cpp и .h, потому что так было в первом туториале. Но недавно скачал open-source проект на GitHub, а там все файлы с расширением .cc. Я попытался переименовать их в .cpp, но компилятор выдал ошибки линковки — говорит, не может найти какие-то функции. Пришлось возвращать обратно. Теперь я запутался: эти расширения взаимозаменяемы или нет? Если да, то почему проект на .cc не работает, когда я переименовываю в .cpp? А если нет, то какое расширение считается «правильным» или «стандартным»? И еще вопрос: влияет ли расширение на то, как компилятор обрабатывает код? Например, может ли он путать C и C++ файлы? Мой пример: я написал простой класс `Cat` в файле `Cat.cc` и main в `main.cc`. Всё компилируется через g++ main.cc Cat.cc -o app. Но если я переименую Cat.cc в Cat.cpp, то g++ main.cc Cat.cpp -o app тоже работает. А вот если я переименую оба файла в .cpp, то линковщик ругается на неопределенную ссылку на конструктор Cat. Почему так? Что я делаю не так? Подскажите, пожалуйста, какое расширение использовать новичку и в чем вообще разница? Очень хочется разобраться, чтобы не было проблем при работе с чужими проектами. <<>>

Краткий ответ: компилятору в целом всё равно, но есть нюансы

Для компилятора GCC и Clang расширение файла — это подсказка, а не строгое правило. По умолчанию:

  • .c — обрабатывается как код на C
  • .cpp, .cc, .cxx, .C (заглавная) — обрабатываются как код на C++
  • .h — может быть как C, так и C++ (зависит от контекста)
  • .hpp, .hxx — обычно считаются C++ заголовками

Таким образом, с точки зрения компиляции .cc и .cpp — это одно и то же. Оба заставят компилятор интерпретировать код как C++. Ваша проблема с линковкой при переименовании — это не проблема расширений, а ошибка в процессе сборки. Скорее всего, вы переименовали файл, но не обновили команду компиляции, и один из объектных файлов остался старым.

Подробное объяснение

Разберем вашу ситуацию по шагам. Допустим, у вас есть два файла:

// Cat.cc
class Cat {
public:
    Cat() {}
    void meow() {}
};

// main.cc
int main() {
    Cat c;
    c.meow();
    return 0;
}

Если вы скомпилируете g++ main.cc Cat.cc -o app, компилятор:

  1. Создаст объектные файлы main.o и Cat.o
  2. Слинкует их в исполняемый файл app

Теперь, если вы переименуете Cat.cc в Cat.cpp и снова выполните g++ main.cc Cat.cpp -o app, всё будет работать, потому что компилятор заново создаст Cat.o из Cat.cpp.

Но если вы сделаете так:

g++ -c main.cc        # создаст main.o
g++ -c Cat.cpp        # создаст новый Cat.o
g++ main.o Cat.o -o app  # линковка

...то всё тоже будет работать. Ошибка "undefined reference" возникает, если в команду линковки попал старый объектный файл от Cat.cc, а нового Cat.o от Cat.cpp нет. Просто удалите все .o файлы перед перекомпиляцией, и проблема исчезнет.

Историческая справка и соглашения

Разные расширения появились по историческим причинам:

  • .cpp — самое популярное на Windows (Visual Studio). Сейчас стандарт де-факто.
  • .cc — традиция Unix-систем (из-за ограничения длины имени в 14 символов в старых файловых системах). Используется в Google, LLVM, Chromium.
  • .cxx — альтернатива, где "xx" символизирует два плюса (++).
  • .C (заглавная) — тоже Unix-традиция, но может путаться с языком C при сортировке.

Для заголовочных файлов:

  • .h — универсально для C и C++
  • .hpp — явно указывает, что это C++ (часто содержит шаблоны или классы)
  • .hxx — реже, но встречается

Что выбрать новичку?

Мой совет: используйте .cpp для исходников и .hpp для заголовков. Это самый распространенный вариант:

  • Visual Studio, CLion, Qt Creator — все по умолчанию создают .cpp
  • Большинство туториалов и книг используют .cpp
  • Меньше путаницы с языком C

Однако если вы работаете в проекте, где принято .cc (Google style guide), придерживайтесь местных правил. Компилятору всё равно, а единообразие в проекте важнее.

Важное предостережение

Никогда не используйте .c для C++ кода! Компилятор обработает его как C и выдаст ошибки на конструкторах, классах и т.д. Если нужно явно указать язык, используйте флаг -x c++:

g++ -x c++ myfile.c -o app  # принудительно обработать .c как C++

Но лучше просто дать файлу правильное расширение.

<<>>

Дополнение: как работают системы сборки (CMake, Make)

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

CMake (самая популярная система):

  • Ищет файлы с расширениями .cpp, .cc, .cxx и включает их в сборку
  • Если вы укажете set(CMAKE_CXX_EXTENSIONS OFF), CMake будет игнорировать нестандартные расширения
  • Рекомендуется указывать файлы явно: add_executable(app main.cpp cat.cpp)

Makefile (классический подход):

  • Вы сами пишете правила. Если в Makefile написано %.o: %.cpp, то файлы .cc не будут обработаны
  • Решение: либо используйте универсальное правило %.o: %.cpp %.cc %.cxx, либо приведите все файлы к одному расширению

Практический совет: если вы скачали проект с .cc файлами, не переименовывайте их. Вместо этого:

  1. Посмотрите, какая система сборки используется (CMakeLists.txt, Makefile, .sln)
  2. Следуйте её инструкциям. Обычно достаточно запустить cmake . или make
  3. Если проект использует .cc, значит, авторы так решили — уважайте их выбор

И последнее: на некоторых платформах (например, встроенные системы, микроконтроллеры) может быть ограничение на длину имени файла. Там .cc или .cxx могут быть единственным вариантом. Но для обычного ПК-разработчика это не актуально.