如何检查PIMPL是否不重新编译客户端类

问题描述 投票:0回答:1

我试图理解PIMPL习惯用法。

我有几个文件,比方说“ Implementation.cpp / Implementation.h”实现了PIMPL习惯用法:它包含一个公共接口和一个私有实现。“ Client.cpp / Client.h”使用公共接口。另一个文件“ main.cpp”仅使用客户端类。我写了一个非常简单的makefile。首先,所有内容都会编译:

g++ -std=c++11 -c main.cpp  
g++ -std=c++11 -c Implementation.cpp  
g++ -std=c++11 -c Client.cpp  
g++ -o main main.o Implementation.o Client.o -std=c++11

我想证明,如果我在PIMPL实现中进行了某些修改,则客户端将不会重新编译,如果我不使用PIMPL习惯用法(如果在公共接口中进行了修改),则客户端将重新编译。

  • 修改私有实现时的编译器输出:

    g ++ -std = c ++ 11 -c Implementation.cppg ++ -o main main.o Implementation.o Client.o -std = c ++ 11

  • 修改公共接口(新方法,具有初始化的新成员等)时的编译器输出:

    g ++ -std = c ++ 11 -c Implementation.cppg ++ -o main main.o Implementation.o Client.o -std = c ++ 11

实际上是相同的。

我的期望是,如果我在公共接口中进行了某些修改,则应该重新编译“实现”和“客户端”:

g++ -std=c++11 -c Implementation.cpp  
g++ -std=c++11 -c Client.cpp  
g++ -o main main.o Implementation.o Client.o -std=c++11

编译器实际上是做什么的,如何使用PIMPL习惯用法检查编译器仅编译必需的东西?

c++ compilation g++ pimpl-idiom
1个回答
0
投票

编译器实际上做什么?>

编译器将编译您要编译的内容。在这里:

g++ -std=c++11 -c Implementation.cpp
g++ -o main main.o Implementation.o Client.o -std=c++11

...您编译Implementation.cpp,并将其与先前编译的main.o和Client.o链接。您不编译Client.cpp或main.cpp。是否修改了翻译单元不会影响编译器的编译内容。

如果您确实在Implementation.h中修改了定义,则您的程序很可能违反了一个定义规则。这样的违反会使程序格式错误,但是不需要使用语言实现来诊断此问题。某些违反行为被链接程序捕获,而其他行为没有被链接程序捕获。

如何检查编译器仅在使用PIMPL惯用语时编译所需的东西?

翻译单元需要

仅在已被修改时才重新编译。由于有了PIMPL,您不需要修改标题,也不需要修改标题,所以您知道不需要重新编译包含该标题的翻译单元。

[当您告诉编译器它将编译的内容时,则无需“检查”-您已经知道您告诉编译器要做什么。

诸如make和ninja之类的构建系统通常会跟踪翻译单元中包含的所有文件的修改时间,并且在时间比以前编译的目标文件还早时跳过重新编译。使用此类工具可以使您不必手动跟踪已修改的内容。通常可以通过检查工具的输出来检查这种工具是否重新编译了特定的源文件。

此外,如果您使用类似ccache前端的内容,则会注意到重新编译未修改的翻译单元要快得多,因为它实际上并不会因为从缓存中加载而重新编译。 Ccache使用翻译单元的缓存内容而不是修改时间来检测更改。

© www.soinside.com 2019 - 2024. All rights reserved.