序言
当我们对某个class(实现)进行修改后,重置程序,原以为只会花几秒时间,可谁知道编译连接时间大大超出我们想象。以下为总结方案去降低文件编译依存关系。
1. 声明式依存关系去替代定义式依存关系
2. handles 类
3. interface 类
接下依次为三种方案进行详细解释
一、 声明替代定义
因为在当我们在头文件中以#include 形式引用某个文件时,你就会发现这引用与定义文件就形成了一种编译依存关系,当某个文件中的类有改动,那么所依赖的其他头文件都会重新编译,这可能会导致连串编译关系导致时间编译过长。
class A
{
};
class A; //不是#include “classA.h”
class B()
{
};
类似于前置声明那种。
二 、 Handle class
由于编译器在编译期间必须知道·对象大小,才能分配足够的空间,如何知道一个分配对象大小,编译器获得这个信息的方法就是通过询问class定义式,如果class定义式没有合法的列出实现项目,那编译器如何知道该分配多少内存空间呢。 但是指针不一样,编译器只需要只需要分配足够的空间给一个指针,有该指针指向对应的对象即可。
这种方案源于以指针对象指向对应实现类,通常这种设计叫pimpl。通常有相应的实现类去完成相应的实际操作。
- 尽量以class声明式替代class定义式
- 如果能尽量使用object 指针与引用能完成任务,就不要要使用对象
- 为声明式与定义式提供不同的文件
- 通常减少不必要的头文件声明
#include "person.h"
#include "personimpl.h"
Person::Person(QString name, QObject* parent)
:QObject(parent)
,m_pImpl(new PersonImpl(name))
{
}
QString Person::getName()
{
m_pImpl->getName();
}
三、 Interface Class
让某个类称为抽象基类,也就是接口interface,在C++中体现为有纯虚函数声明,具体有子类其实现。通过父类指针或者引用去指向实际应用过程中派生类,除非接口有修改,否则其使用客户端不用重新编译。
Interface class 客户必须有一种能将子类真正具体化的构造函数功能,其返回智能指针(指针)能指向动态分配的对象,而该对象能支持interface class 接口,这个函数通常被声明为static。
#include <QString>
#include <iostream>
class Person
{
public:
Person(){}
~Person(){}
virtual QString getName() const = 0;
static std::tr1::shared_ptr<Person> create(const QString& name);
};
#include "person.h"
#include "student.h"
std::tr1::shared_ptr<Person> Person::create(const QString &name)
{
return std::tr1::shared_ptr<Person>(new Student(name));
}
#include "person.h"
#include <QString>
class Student: public Person
{
public:
Student(const QString& name)
{
m_name = name;
}
~Student()
{
}
QString getName() const
{
return m_name;
}
private:
QString m_name;
};