对于下面的代码:
- #include
- #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 m_Name;
- Date m_BirthDate;
- Address m_Address;
- };
如果有很多文件使用到了Person对象,如果Date类中的实现做了修改,那么所有的文件都需要被重新编译。是因为Person类的三个成员变量既不是指针也不是引用,所以编译器在编译这个文件时必须访问这三个类型的定义式,否则无法得知该给这三个变量分配多少内存。也就是说,如果你修改了Date或Address的定义,然后重新编译,Person类所在的文件和使用Person对象的文件也不得不重新编译。
但是如果对Person类做如下修改,就不会导致重新编译:
- #include
-
- class Date;
- class Address;
-
- 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* m_Name;
- Date* m_BirthDate;
- Address* m_Address;
- };
因为编译器为指针分配的字节大小是固定的,因此不需要知道Date类和Address类的具体实现。
因此尽量用指针和引用代替Object;尽量用class声明代替class定义式。在函数声明中,即使用到某个class,并不需要访问定义式,即使是使用by value的方式传参。
下面的代码,把Person的具体实现都放在PersonImpl中,这样当Date等类的实现发生改变时,不需要重新编译Person文件,只需要重新编译Personimpl即可,这样可以做到解耦合。
- #include
- #include
-
- class PersonImpl;
- class Date;
- class Address;
- class Person {
- public:
- Person( const std::string& name,const Date& birthday,const Address& addr);
- std::string name() const;
- std::string birthDate() const;
- std::address() const;
- ...
- private:
- std::tr1::shared_ptr
pImpl; - };
还可以使用纯虚函数的方法降低文件之间的依赖,这里不再赘述。