关于“类”的“前置声明”

本文探讨了C++中类的前置声明技巧,特别是在Qt框架下如何提高编译效率。通过仅在头文件中声明类而非包含完整头文件,可以避免因源代码更新导致的大规模重新编译,显著提升开发效率。然而,该方法仅适用于指针类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于“类”的“前置声明”

“前置声明”这个东西,应该不陌生,很多函数在使用之前都要进行一个前置声明。

今天想说的,实际上是在Qt的学习过程中,对于“类”的前置声明。

这个东西实际上还是挺常用的,而且作用也很大(这个还是我这两天才知道的),这个常用其实指的是对于C++大佬来说比较常用,像我这种菜鸡,要不是领导推荐让用,我都不知道还有这个玩意,由此可见我是有多菜了。

废话不多说,说一下它的优点:

主要优点体现在“效率”上,这个效率主要包括两个部分:

1.编译的时候:因为采用的是类的前置声明,因此在.h文件中不需要包含所需文件的头文件,只需要使用class进行声明一下即可,如#include ->class QLabel, 在.cpp中添加完整的头文件。

2.所包含的源代码发生更改的时候:这个才是它最主要的作用,就是比如说某一天,QLabel的源文件发生了更改,那么对于所有包含着“QLabel”的文件在编译的时候都得重新编译一遍,这样会极大地降低效率。而如果采用了前置声明,那么在发生更改的时候,需要变化的仅仅是.cpp文件,这样效率就高多了。

虽然类的前置声明很好用,但是并不意味着所有的都可以使用前置声明,其实能利用类的前置声明的,目前我只发现一种,那就是“指针”。

如QLabel *m_pLbl;

指针能够采用类的前置声明的原因是因为,无论是何种类型的指针,它的大小永远都是4个字节(32位),那么在头文件的预处理过程中,分配四个字节就可以了,不需要考虑它的具体实现。

如果不是指针,如QLabel m_lbl1,则不能使用类的前置声明,必须采用包含完整的头文件。

在一个头文件中再包含一个那么大的头文件着实不是一种好的编程风格,尤其是对于比较大的工程项目更是如此。

总结:使用的前提就是“指针”,优点在于“效率高”。

### 前置声明与模板结合使用的语法结构 在 C++ 中,前置声明通常用于减少头文件之间的依赖关系,从而提高编译效率并降低耦合度。当涉及模板时,可以将模板作为参数传递给或函数,或者通过模板来定义本身。 以下是关于如何实现前置声明与模板结合的具体方法: #### 前置声明模板 如果某个是一个模板,则可以在其他地方对其进行前置声明以便于后续使用。例如,在某些情况下可能只需要指针而不需要完整的定义,此时可以通过前置声明优化性能。 ```cpp // 声明一个名为 TemplateClass 的模板 (前置声明) template <typename T> class TemplateClass; // 定义另一个普通的 B,它只持有指向 TemplateClass<T> 的指针 class B { TemplateClass<int>* ptr; }; ``` 上述代码展示了如何对 `TemplateClass` 进行前置声明,并将其用作另一中的成员变量型[^1]。 #### 使用模板作为的友元 有时我们需要让特定型的模板成为某的朋友(friend)。这允许该模板访问私有部分的数据成员和方法。 ```cpp template<typename U> class FriendTemplate; class MyClass { private: int secretValue = 42; // 将所有实例化的 FriendTemplate<U> 设置为朋友 template<typename U> friend class FriendTemplate; }; template<typename U> class FriendTemplate { public: void accessSecret(MyClass& obj) const { std::cout << "Accessing private member: " << obj.secretValue << '\n'; } }; ``` 在此例子中,任何由 `FriendTemplate` 实例化出来的对象都可以存取 `MyClass` 的内部数据[^2]。 #### 结合非型模板参数的例子 现代标准还支持非型模板参数,这意味着除了常规的数据型外还可以传入整数常量等值到模板里去定制行为模式。 ```cpp #include <iostream> template<std::size_t N> struct ArrayWrapper { double data[N]; constexpr std::size_t size() noexcept { return N; } double& operator[](std::size_t idx) { if(idx >= N){ throw std::out_of_range("Index out of bounds"); } return data[idx]; } }; int main(){ ArrayWrapper<3> array {}; try{ for(auto i=0u;i<=array.size(); ++i){ array[i]=static_cast<double>(i); std::cout<<array[i]<<" "; } }catch(const std::exception &e){ std::cerr<<"\nError:"<<e.what(); } } ``` 此片段创建了一个固定大小数组封装器,利用了非型模板参数指定长度。 ### 总结 以上介绍了几种常见场景下的 C++ 模板配合前置声明的应用方式,包括但不限于简单模板的提前告知、设置模板型别的友好权限以及引入数值作为额外约束条件的技术手段。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值