3

前向声明可以隐藏依赖关系,允许用户代码在标头更改时跳过必要的重新编译。

来自https://google.github.io/styleguide/cppguide.html#Forward_Declarations

我最近了解到,关于是使用前向声明还是仅将标头包含在标头本身中存在一些争论。在工作中,我们向前声明我们的内部类(不是库代码),并在相应的.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 实际上从不需要知道 Test 的大小才能到达doWork(). 所以,我们不需要包含Test.h. 只有真正起作用的函数 ( doWork) 才需要包含在它的 cpp 中。通过使用前向声明,对 MyClass.cpp 的更改Test.h不会导致任何重新编译。但在我看来这是一件好事,因为它不是必要的重新编译。

免责声明:谷歌风格指南有一个与 void* 相关的示例,但我不确定它是否与此要点相关;因为它只是一个不正确的函数调用,而不是必要的重新编译。另外,我相信如果函数是在 .cpp 中定义的并且它们包含适当的类,那么特定示例将被消除。此外,如果它与我在这个问题中的要点有关,那么缓解与 void* 相关的问题听起来不足以完全禁止使用前向声明。

所以,我的问题是——是否有任何具体的例子可以跳过必要的重新编译?

编辑:这不是链接帖子的副本,因为该答案仅包含 void* 响应。我在这个问题中表示,我正在从给出的 void* 中寻找任何其他示例。IMO 是一个非常深奥的问题(希望在现代 c++ 中并不常见)完全放弃使用前向声明。在我看来,就像创建一个从不使用引用的规则,包括按引用传递,因为类成员引用可以通过默认副本轻松产生悬空引用

4

0 回答 0