#c #include
Вопрос:
В следующем сценарии, каков был бы наилучший подход для включения <string>
заголовка?
main.cpp
#include "extra.h"
int main() {
func("A string");
return 0;
}
дополнительно.ч
#ifndef EXTRA_H
#define EXTRA_H
#include <string>
void func(std::string);
#endif
extra.cpp
#include <iostream>
#include "extra.h"
void func(std::string str) {
std::cout << str << 'n';
}
Комментарии:
1. Код, который у вас есть, выглядит правильно. Не могли бы вы более конкретно сформулировать свой вопрос?
2. Извините за отсутствие деталей. Я прошел через несколько различных руководств, и некоторые из них рекомендуют включать заголовочные файлы в файлы .cpp, а не полагаться на транзитивное включение, поэтому мне было интересно, следует ли добавить
#include <string>
строку в extra.cpp и main.cpp так же хорошо.3. Что такое «лучшее», довольно субъективно. Лично я, как правило, включаю то, что использую, но в данном случае это может быть больше похоже на стиль. Если одни и те же разработчики контролируют
.h
файлы.cpp
и , и вы точно знаете, чтоextra.h
включает<string>
, то вы можете счесть необязательным включать его в.cpp
. Но это только мое мнение.
Ответ №1:
Ваш extra.h
включает <string>
в себя, потому что он использует его напрямую. В вашем нет прямого использования std::string
main.cpp
, поэтому было бы странно включать <string>
его туда.
Далее, в том числе <string>
в extra.cpp
совершенно излишним, поскольку использовать std::string
это в функции, которые вы знаете, объявлен в extra.h
плюс на содержание двух extra
файлов может быть выполнена в ходе одной операции, так что нет необходимости беспокоиться о extra.h
вдруг не включая <string>
, а потом ломать extra.cpp
, потому что они будут сохраняться вместе.
Ответ №2:
Файл заголовка должен содержать как можно меньше элементов. Это обеспечивает его чистоту, а также позволяет ускорить компиляцию. Если файл заголовка требует полного типа, необходимо включить файл включения для этого типа в файл заголовка, в противном случае используйте прямые объявления.
Например, main.h
#pragma once
// if your header uses a full type (see function h)
// it needs to know the size of the type
// then include header file for that type in your header
#include <string>
void h(std::string str);
// if your header only has references or pointers to a type
// then add a forward declaration of that type.
// The compiler only has to know the size for the reference/pointer
struct struct_t;
void f(const struct_tamp; s);
void g(const struct_t* s);
А потом main.cpp
#include "main.h"
#include <iostream>
// #include <string> not really needed already done in "main.h"
// full declaration of struct_t in the place where it is needed.
// note this could also be in done in its own header file.
struct struct_t
{
int value1;
int value2;
};
void f(const struct_tamp; s)
{
std::cout << s.value1 << std::endl;
std::cout << s.value2 << std::endl;
}
void g(const struct_t* s)
{
std::cout << s->value1 << std::endl;
std::cout << s->value2 << std::endl;
}
void h(std::string s)
{
std::cout << s << std::endl;
}
int main()
{
struct_t values{ 0, 42 };
f(values);
g(amp;values);
h("Hello World!");
}
Комментарии:
1. Будет ли обертывание строки в структуру (структуру, класс и т. Д.) Более эффективным, Чем включение
<string>
заголовка в extra.h?2. Я приношу извинения за путаницу, обертывание строки было не тем, что я хотел показать, я обновил пример.
3. Если вы создаете набор заголовочных файлов для клиента, то да, скрытие сложных типов от клиента является допустимым подходом, но тогда я обычно использую абстрактные базовые классы (интерфейсы) и шаблон pimpl : en.cppreference.com/w/cpp/language/pimpl . Но это был не ваш первоначальный вопрос 🙂