如何减少C++程序编译需要的时间

本文探讨了在C++编程中,因编译时间过长而引发的问题及其原因,并提出了解决方案。通过将接口与实现分离,避免在头文件中包含不必要的内容,可以显著减少编译时间,提高开发效率。正确做法是创建单独的接口类,以接口声明式代替class定义式,确保接口与实现的真正分离。

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

前言

假如你对C++程序的某个class实现文件做了轻微的修改。注意,修改的不是class接口,而是实现,而且只改private部分。然后重新编译整个程序,预计只花几秒就好,结果你发现得花费数倍这个时间,仿佛整个程序重新编译了!当你碰到这种事情的时候,你不想骂人吗?

让我们来看以下的代码

#include <string>
#include "date.h"
#include "address.h"

class Person {
public:
	Person(const std::string &name, const Date &birthday, const Address &addr);
	std::string name() const;
	std::string birthDate() const;
	std::string address() const;
...
private:
	std::string theName;
	Date theBirthDate;
	Address theAddress;
}

一眼看下去,语法上没什么问题,也能编译得过,不幸的是,这么一来便是在Person定义文件和其含入文件之间形成了一种编译依存关系。如果这些头文件中有任何一个被改变,或这些头文件所依赖的其他头文件有任何改变,那么每一个含入Person class的文件就的重新编译,任何使用Person class的文件也必须重新编译。这样的连串编译依存关系会对许多项目造成难以形容的灾难。

为什么会出现这种情况?

因为编译器在编译期间需要知道对象的大小,当编译器看到Person对象,它获取这项信息的唯一办法就是询问class定义式,所以如果你尝试把#include "date.h"和#include “address.h”删掉,你会发现程序根本编译不过。还好C++有前置声明,帮我们很好的解决这个问题,往下看。

正确的做法

把Person分割成两个classes,一个只提供接口,另一个负责实现该接口。负责实现的那个implementation class取名PersonImpl

// Person.h
#include <string>
#include <memory> // shared_ptr需要包含的头

class PersonImpl;	// Person实现类的前置声明
class Date;		// Person接口用到的classes的前置声明
class Address;
class Person {
public:
	Person(const std::string &name, Date* birthday, Address* addr);
	std::string name() const;
	std::string birthDate() const;
	std::string address() const;
...
private:
	std::tr1::shared_ptr<PersonImpl> pImpl;	// 智能指针,防止内存泄漏
}

// Person.cpp
std::string Person::name() const
{
	return pImpl->name();
}

std::string Person::birthDate() const
{
	return pImpl->birthDate()
}

std::string Person::address() const
{
	return pImpl->address();
}

优点

这样的设计之下,Person的客户就完全与Dates,Addresses以及Persons的实现细目分离了。那些classes的任何实现修改都不需要Person客户端重新编译。此外由于客户无法看到Person的实现细目,也就不可能写出什么“取决于那些细目”的代码,这是真正的"接口与实现分离"。

设计策略

  • 如果使用对象引用或对象指针可以完成任务,就不要使用对象。
  • 如果能够,尽量以class声明式替代class定义式。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值