Это на самом деле не имеет ничего общего с Catch или тестированием.Когда вы #include
файл в C ++, он вставляется в копию в дословной строке #include
.Если вы поместите определения свободных функций в заголовки, вы увидите, что эта проблема строит вашу реальную программу и т. Д.
Основная проблема заключается в том, что #include
- это не тот тип директивы import-a-module, какэквивалентная директива (import
, require
и т. д.) в большинстве языков, которые делают нормальную вещь в такой ситуации (подтвердите, что заголовок тот же, что мы уже видели, и игнорируйте повторное определение метода).
Комментатор, предложивший вам написать inline
, технически корректен в том смысле, что это «решит вашу проблему», поскольку ваш компилятор не будет генерировать объектный код для метода несколько раз.Однако в действительности это не объясняет, что происходит, или не решает основную проблему.
Чистое решение:
- В
test_utils.hpp
замените определение метода наметод объявление : void something_great();
. - Создать
test_utils.cc
с определением метода (которое вы в настоящее время используете в .hpp
). clang++ -std=c++17 test1.cc -c
clang++ -std=c++17 test2.cc -c
clang++ -std=c++17 test_main.cc -c
clang++ -std=c++17 test_utils.cc -c
clang++ -std=c++17 test1.o test2.o test_utils.o test_main.o
Я также рекомендую вамПрочитайте это: В чем разница между определением и объявлением?
Явно:
// test_utils.hpp
#pragma once
// This tells the compiler that when the final executable is linked,
// there will be a method named something_great which takes no arguments
// and returns void defined; the definition lives in test_utils.o in our
// case, although in practice the definition could live in any .o file
// in the final linking clang++ call.
void something_great();
И:
// test_utils.cpp
#include "test_utils.hpp"
#include <iostream>
// Generates a DEFINITION for something_great, which
// will get put in test_utils.o.
void something_great() { std::cout << "Hi\n"; }
Кажется, вы беспокоитесь о «перекомпиляции Catch» каждый раз, когда вносите изменения в тест.Я не хочу рассказывать вам об этом, но вы сейчас находитесь на земле C ++: вы будете бессмысленно много перекомпилировать материал.Библиотеки только для заголовков, такие как Catch, ДОЛЖНЫ быть до некоторой степени «перекомпилированы» при изменении исходного файла, включающего их, потому что, к лучшему или худшему, если исходный файл или файл заголовка, включенный транзитивно из исходного файла, включает catch2.hpp
, то исходный файлкод catch2.hpp
будет проанализирован компилятором при чтении этого исходного файла.