关于前置声明:#include类和前置class类名的区别

简介: 关于前置声明:#include类和前置class类名的区别

一、先来看例子


今天看别人写的代码,用到了QTreeWidgetItem,这是QT自带的类,但是并没有#include<QTreeWidgetItem>

而是在头文件里写了类的声明:

image.png



然后用到这个类的函数接口:


image.png


你看用到的都是指针!

原来是因为当你在头文件声明成员变量或成员函数时,如果只需要用到某个类的指针而不需要用到类的对象,那么就可以直接只是声明一下这个类,不用include,这样可以避免编译时include编译这个类。

但是cpp实现文件里是需要include类的。

这样的方法同样适用于自己写的类:


image.png




二、再来看Google的文档说明


https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/headers/#forward-declarations


定义:


所谓「前置声明」(forward declaration)是类、函数和模板的纯粹声明,没伴随着其定义.


优点:


前置声明能够节省编译时间,多余的 #include 会迫使编译器展开更多的文件,处理更多的输入。

前置声明能够节省不必要的重新编译的时间。 #include 使代码因为头文件中无关的改动而被重新编译多次。

缺点:


前置声明隐藏了依赖关系,头文件改动时,用户的代码会跳过必要的重新编译过程。


前置声明可能会被库的后续更改所破坏。前置声明函数或模板有时会妨碍头文件开发者变动其 API. 例如扩大形参类型,加个自带默认参数的模板形参等等。


前置声明来自命名空间 std:: 的 symbol 时,其行为未定义。


很难判断什么时候该用前置声明,什么时候该用 #include 。极端情况下,用前置声明代替 includes 甚至都会暗暗地改变代码的含义:


// 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 被 B 和 D 的前置声明替代, test() 就会调用 f(void*) .


前置声明了不少来自头文件的 symbol 时,就会比单单一行的 include 冗长。

仅仅为了能前置声明而重构代码(比如用指针成员代替对象成员)会使代码变得更慢更复杂.

结论:


尽量避免前置声明那些定义在其他项目中的实体.

函数:总是使用 #include.

类模板:优先使用 #include.




---

参考文献

https://blog.csdn.net/weixin_40098626/article/details/80117901


相关文章
|
3月前
|
Java PHP 数据安全/隐私保护
PHP 面向对象,构造函数,析构函数,继承,方法的重写,接口抽象类,static,final,this,parent,self的异同和作用
本文详细介绍了PHP面向对象编程的一系列核心概念和用法,包括构造函数、析构函数、继承、方法重写、访问控制、接口、抽象类、静态成员、final关键字、以及this、self、parent这三个关键字的异同和作用。通过具体示例代码,展示了如何在PHP中使用这些面向对象的特性,以及它们在实际开发中的应用。
PHP 面向对象,构造函数,析构函数,继承,方法的重写,接口抽象类,static,final,this,parent,self的异同和作用
|
2月前
|
Java 编译器
【一步一步了解Java系列】:子类继承以及代码块的初始化
【一步一步了解Java系列】:子类继承以及代码块的初始化
144 3
|
4月前
|
编译器 C语言 C++
类和对象 | 类的引入、struct&class的区别、类的定义
类和对象 | 类的引入、struct&class的区别、类的定义
37 7
|
4月前
|
C++
CPP语法(四)——类的声明和定义
CPP语法(四)——类的声明和定义
41 0
|
7月前
|
JavaScript 前端开发
ES6如何声明一个类?类如何继承?
ES6如何声明一个类?类如何继承?
48 0
|
7月前
|
存储 C语言 C++
C/C++静态static属性/用法
C/C++静态static属性/用法
55 0
|
druid Java 编译器
Java的第七篇文章——面向对象接口(包含了接口、static修饰符、final修饰符、main方法、内部类等知识点)
Java的第七篇文章——面向对象接口(包含了接口、static修饰符、final修饰符、main方法、内部类等知识点)
|
存储 Java
Java基础:static的理解(含义、用法及静态修饰的优先顺序)
Java基础:static的理解(含义、用法及静态修饰的优先顺序)
242 0
Java基础:static的理解(含义、用法及静态修饰的优先顺序)
|
Java 开发者
Class 类对象的三种实例化模式|学习笔记
快速学习 Class 类对象的三种实例化模式
182 0
Class 类对象的三种实例化模式|学习笔记
|
架构师 Java
[Java Base] 类,接口,枚举,静态常量到底应该放在哪?
静态常量什么时候适合放在类中?什么时候适合放在接口中?什么时候适合放在枚举中呢?放在不同的type中会引发什么不良后果呢?本篇就来解析一下~常量类应该是final,不变的,而接口里的参数是final,也是不变的。那么,看起来接口是放常量没有一定问题,还省去了final的输入,非常的合适。但是,类是只能单继承的,接口是允许多实现的。要是类实现的多个接口出现重名的常量,会报错,必须要在实现类明确常量用的是哪个接口的。
274 0