C++前置声明 和 #include

118 篇文章 8 订阅

如何看待C++前置声明?

C++前置声明 和 #include

c++中前置声明和#include

Qt 中类的 前向声明 和#include的区别 https://blog.csdn.net/ken2232/article/details/136126779

C++前置声明 和 #include   https://blog.csdn.net/ken2232/article/details/136126609

====================================

如何看待C++前置声明?

  https://www.zhihu.com/question/63201378

利益相关:在Google写了4年C++。

我是经历了Google内部从『倾向于使用前置声明』到『倾向于使用#include』的这个过程的。事实上在很多年前Google内部就开始了对这两者的比较和探讨。在2014年,内部有一篇总结性文章指出了前置声明

将造成的十种危险。最终C++ Code Style经历了一个过渡期之后全面倒向了#include。

简单来说,前置声明最大的好处就是『节省编译时间』。毕竟C++

的编译时间长已经是一个臭名昭著人人喊打的问题。但对于Google来说,这方面的效率节省就不见得那么可观了——毕竟Google内部有超大规模的分布式编译集群

『Forge』。哪怕是十万以上的target,全部build一遍也就是几分钟的事情。

与此同时,前置声明带来的问题则显得更加关键:

例如,如果一个类的实现者需要把这个类改个名字/换个命名空间

,出于兼容性他原本可以在原命名空间里/用原名通过using来起一个别名指向新类。然而别名不能被前向声明

。内网有一份代码改动一下子试图修改总计265个头文件,就是实现者为了要改这个类的名字而不得不去改所有的调用处。想一想,如果这265个文件分属于50个不同的团队,你得拿到50个人的同意才能提交这份改动,想不想打人?

再举一个code style中提到的,更为严重的例子——它可能导致运行时出现错误的结果

// b.h:
struct B {};
struct D : B {};

// good_user.cc:
#include "b.h"
void f(B*);
void f(void*);
void test(D* x) { f(x); }  // calls f(B*)

若把#include换成前置声明,由于声明时不知道D是B的子类

,test()中f(x)就会导致f(void*)被调用,而不是f(B*)。

再比如,C++标准5.3.5/5中规定,delete一个不完整类型的指针时,如果这个类型有non-trivial的析构函数

,那么这种行为是未定义的。把前置声明换成#include则能保证消除这种风险。

诚然,从理论上说,一个牛逼的程序员当然是可以通过分析一个头文件

的源码来决定会不会碰到以上诸多坑,并由此决定用哪个好。但一来不是所有人都是牛逼程序员,二来,把精力花费在这件事情上真的值得吗?

编辑于 2017-08-03 16:00

fullsail

前置声明最大的好处在于,避免编译膨胀。一个优秀的CPP代码应该只包含他的最小代码集合。

但前置声明并不能解决所有问题,他只在您的成员是指针时才能奇效,否则是必须使用#inlcude引入的相关头文件的,否则编译器无法知道结构的大小。而将成员都调整为指针,这个其实浪费了很多C++的编写优势(构造,析构等)。所以没有必要过分使用。如google那位兄弟说的,他们解决了编译的速度问题,就更不在乎使用前置声明了。但代码设计过程,还是会出现交叉引用,即使你再小心也不能完全避免。

乎用户

前置声明隐藏依赖啊亲们,扯什么编译时间啊。

没听说过 pImpl?

不用前置声明难道直接把 Windows.h 那一坨屎扔在头文件里让别人吃屎么……

乎用户

说简单点,就是尽量避免循环依赖

代码之诗

这个问题没必要长篇大论,我尽量简短:

  1. 头文件本身应当尽量减小不必要耦合,其中包括尽量少 include 引入无关要素;
  2. 代码规模较大时,前置声明容易发生“小修改引起大雪崩”。但这不是反对前置声明的理由,而应该把写前置声明的责任移交给写头文件的团队。象标准库一样,既有 iostream,又有 iosfwd。大家只需要 include,仍然享受到了前置声明的好处。
  3. 即使代码规模不大,相关的前置声明也可以自己写一个头文件,相对集中处理。

我的结论:尽可能使用前置声明,但不要写得到处都是。



作者:代码之诗
链接:https://www.zhihu.com/question/63201378/answer/2574824272
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

c++中前置声明和#include

  https://blog.csdn.net/xiaofeilongyu/article/details/119859638

c++中前置声明和#include
  • 能用前置声明的尽量用前置声明,尽可能的避免用#include头文件
  • 尽量在cpp文件中包含头文件,而非在头文件中

。。。(略)。。。

编译器编译需要知道文件的大小,所以当类B中以指针的形式引用类A时可以使用前置声明,单若时用到了类A的对象那就必须使用#include包含类A的头文件
具体情况如下:

  • B继承A,必须#include A.h,需要获得A的定义
  • B有一个指针类型为A的成员变量,前置声明就可以
  • B有一个引用类型为A的成员变量,前置声明
  • B有一个不同类型为A的成员变量,需要使用#iclude A.h
  • B用使用到标准模板库,例如vector< A >,前置声明九月可以,标准模板库内部使用的是指针作为成员变量
  • B中有函数成员函数返回类型和参数为A的,前置声明
  • B中有函数成员函数返回类型和参数为A的,并且在头文件中定义此函数并调用A中的成员或函数,需要#iclude A.h

。。。(略)。。。

使用前置声明可解决相互依赖头文件相互依赖问题
前置声明的作用
1、解决class相互依赖问题
2、降低文件之间的编译依赖关系
3、前置声明可以实现接口与实现分离,提供给客户的类分为两个class,一个用来提供接口,一个负责实现;
https://blog.csdn.net/u011913417/article/details/100183653
https://www.cnblogs.com/rednodel/p/5000602.html

C++前置声明 和 #include

  https://www.cnblogs.com/sggggr/p/16938612.html

阅读目录

如何看待C++前置声明? - 知乎

回到顶部

前置声明用处:

1.前置声明能够节省编译时间
2.在两个类相互引用时用前置声明
当然应当尽量避免这样设计,需要依赖倒置规避
3.前置声明,在写wrapper的时候,会发现是屏蔽内部宏定义的好方法

比如,需要写一个动态库,并提供头文件给别人使用,头文件是这样的

class ImgAnalysis;

DLL_EXPORT ImgAnalysis* create_img_analysis(const ImgAnalysisCfg *cfg);
DLL_EXPORT int run_img_analysis(ImgAnalysis* img_analysis, ImgAnalysisInput* input);
DLL_EXPORT void destory_img_analysis(ImgAnalysis* img_analysis);

ImgAnalysis这个类里面有很多成员变量,依赖其它很多头文件,如果不前置声明,就要放在这个头文件中,那别人使用这个头文件,就要把ImgAnalysis这个类需要的头文件全包含进来,有前置声明,这个头文件才能如此干净,使用的人也方便很多。如果没有前置声明,还有一种方法就是void指针,然后强制类型转换,不过我是极度讨厌void的,void*一眼看不出类型, 能不用就不用。

回到顶部

前置声明的劣势

例如,如果一个类的实现者需要把这个类改个名字/换个命名空间,出于兼容性他原本可以在原命名空间里/用原名通过using来起一个别名指向新类。然而别名不能被前向声明。内网有一份代码改动一下子试图修改总计265个头文件,就是实现者为了要改这个类的名字而不得不去改所有的调用处。想一想,如果这265个文件分属于50个不同的团队,你得拿到50个人的同意才能提交这份改动,想不想打人?

// b.h:
struct B {};
struct D : B {};

// good_user.cc:
#include "b.h"
void f(B*);
void f(void*);
void test(D* x) { f(x); }  // calls f(B*)

若把#include换成前置声明,由于声明时不知道D是B的子类,test()中f(x)就会导致f(void)被调用,而不是f(B)。
等等

回到顶部

结论:

还是用#include比较稳妥,写库的时候可能会用到前置声明

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值