c++ 前置声明

51 篇文章 2 订阅
本文介绍了C++中使用前置声明(class声明)替代#include头文件的方式,以减少编译依赖和提升效率。前置声明仅适用于指针或引用,且在特定条件下使用,如类作为成员或函数参数。使用前置声明可以降低文件间的编译依赖,减少不必要的编译。文章还探讨了何时需要使用#include,并展示了如何在Person类中使用前置声明来隔离实现,减少了编译需求。
摘要由CSDN通过智能技术生成

#pragma once
class bar;
class foo
{
public:
    Bar getBar();
private
    Bar* _bar;
};

即:在.h文件中用class 声明代替include头文件

前置声明只能作为指针引用,不能定义类的对象,自然也就不能调用对象中的方法了。

前置声明要求:

1.其声明的类是文件所声明的类的数据成员时,是指针成员或引用成员(而不是对象成员);

2.其声明的类是文件所声明的类的成员函数的参数返回值时,该函数在文件中不存在定义。   

 原因:其声明的类是文件所声明的类的数据成员时,因为编译器申请空间时需要其定义,而指针需要的空间固定(引用的实现也基于指针)。   其声明的类是文件所声明的类的成员函数的参数或返回值时,因为函数的声明并没有使用到该类的定义,而函数的定义则很大可能使用到该类的定义。但是一般情况下,除非函数定义极短,否则成员函数的声明和定义一般是分离在.h文件和.cpp文件中的,所以可以说其声明的类是文件所声明的类的成员函数的参数或返回值时可以使用前置声明。

为什么使用前置声明

  • 当两个类相互包含头文件时无法通过编译。(必须使用)
  • 有助于分离类的声明和定义文件。(只在.cpp文件中include .h文件)(按照个人风格)
  • 节省编译时间。(修改某个头文件后需要编译多个无关的依赖文件)(按照需求)前置声明隐藏了依赖关系,头文件改动时,用户的代码会跳过 必要的重新编译过程。关于类与类的关系,总共有6种,具体见c++类之间的基本关系_baidu_16370559的博客-CSDN博客

延伸:

1.定义式:就是.h文件中用include其他头文件

2.使用前置声明,在.h文件中用class,在.cpp还是要include其他使用到的头文件,虽然这样,还是可以减少部分文件的编译。表现在:

总之,此时任何接口类头文件产生的变化只会导致接口类头文件的变化而重新编译,以及Person实现文件由于include了接口类的头文件也要重新编译;而Person类头文件由于只使用了类的声明式,所以并不会重新编译,因此所有使用Person类的对象的文件也都不需要重新编译了,这样就大大降低了文件之间的编译依存关系。

注意:对于C++类而言,如果它的头文件变了,那么所有这个类的对象所在的文件都要重编,但如果它的实现文件(cpp文件)变了,而头文件没有变(对外的接口不变),那么所有这个类的对象所在的文件都不会因之而重编。

// Person.h
#include <string>
using namespace std;

class PersonImp;
class Date;
class Address;

class Person
{   
public:
    Person(const std::string& name,const Date& birthday,const Address& addr);
    string Name() const;
    string Birthday() const;
    string Address() const;

private:
    //string Name;            之前的定义方式,并且以include头文件实现
    //Date Birthday;
    //Address Address;
    std::tr1::shared_ptr<PersonImp> pImpl;     
    //通过提供的PersonImp接口类指针替换实现Person,起到了隔离的作用

// Person.cpp
#include "Person.h"                     //正在实现Person类
#include "PersonImpl.h"                 //使用PersonImp接口类实现Person
                                        //类,必须使用其成员函数,所以要
                                        //include接口类头文件
Person::Person(const std::string& name,const Date& birthday,const Address& addr)
:pImpl(new PersonImpl(name,birthday,addr))
{ }
string Person::Name() const
{
    return pImpl->Name();
}
...                                      //其余函数实现

// PersonImp.h
#include <string>
#include "MyAddress.h"
#include "MyDate.h"
using namespace std;

class PersonImp                 //充当一个接口类,成员函数和Person相同,供
                                //Person类通过指针调用
{
public:
    string Name() const
    {
        return Name;
   }
   ...                          //其余成员函数定义

private:
    string Name;                //放置了所需的外来类对象
    MyAddress Address;
    MyDate Birthday;
};

#include 和前置声明_baidu_16370559的博客-CSDN博客


 

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值