Почему предварительное объявление может скрыть зависимость и заставить пользовательский код пропустить необходимую перекомпиляцию? (Руководство по стилю Google C ++) - PullRequest
1 голос
/ 31 января 2020

Перенаправленные объявления могут скрыть зависимость, позволяя пользовательскому коду пропускать необходимую перекомпиляцию при изменении заголовков.

из 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 ++), которую можно полностью исключить с помощью предварительных объявлений. Мне кажется, что создание правила никогда не использовать ссылки, включая передачу по ссылке, поскольку ссылки на члены класса могут легко привести к появлению висячих ссылок через копию по умолчанию

...