Перенаправленные объявления могут скрыть зависимость, позволяя пользовательскому коду пропускать необходимую перекомпиляцию при изменении заголовков.
из https://google.github.io/styleguide/cppguide.html#Forward_Declarations
I недавно узнали, что есть некоторые споры о том, использовать ли предварительное объявление или просто включить заголовок в сам заголовок. На работе мы объявляем наши внутренние классы (не код библиотеки) и включаем заголовки, содержащие эти классы, в соответствующие .cpp
. Если код в .cpp
никогда не использует класс, то включение может быть полностью пропущено; например, он передает тип.
скажем, у нас есть следующий код и файлы
#pragma once
//test.h
class Test{
public:
void foo() const;
};
//test.cpp
#include<iostream>
#include "test.h"
void Test::foo() const
{
std::cout << "test" << std::endl;
}
#pragma once
//worker_function.h
class Test;
void doWork(const Test&);
//worker_function.cpp
#include"worker_function.h"
#include"Test.h"
void doWork(const Test& obj){
obj.foo(); //must include for compilation
}
#pragma once
//myclass.h
class Test;
class MyClass{
public:
void passthrough(const Test& obj);
};
//myclass.cpp
#include "myClass.h"
#include "worker_function.h"
void MyClass::passthrough(const Test& obj){
doWork(obj);
}
MyClass на самом деле не нужно знать Размер теста до doWork()
. Итак, нам не нужно включать Test.h
. Только действующая функция (doWork
) должна быть включена в cpp. При использовании предварительных объявлений изменения в Test.h
не вызовут перекомпиляции MyClass. cpp. Но, на мой взгляд, это хорошо, потому что это не обязательная перекомпиляция.
Отказ от ответственности: в руководстве по стилю Google есть пример, связанный с void *, но я не уверен, что он связан с этим пунктом; поскольку это просто неправильный вызов функции, а не необходимая перекомпиляция. Кроме того, я считаю, что этот конкретный пример был бы исключен, если бы вместо этого была определена функция в. cpp, и они включали соответствующие классы. Кроме того, если это относится к пункту, который у меня есть в этом вопросе, смягчение вопросов, связанных с void *, не представляется достаточно обоснованным, чтобы полностью запретить использование предварительных деклараций.
Итак, мой вопрос - есть ли конкретный пример случая, когда он пропустит необходимую перекомпиляцию?
edit: Это не дубликат связанного поста, так как этот ответ содержит только недействительный * ответ. В этом вопросе я заявил, что ищу любой другой пример из приведенной пустоты *. IMO, это довольно сложная проблема c (надеюсь, не распространенная в современном c ++), которую можно полностью исключить с помощью предварительных объявлений. Мне кажется, что создание правила никогда не использовать ссылки, включая передачу по ссылке, поскольку ссылки на члены класса могут легко привести к появлению висячих ссылок через копию по умолчанию