1. Compile Dependencies
In some cases, only the private of a class is modified, but a large number of files need to be compiled. The problem is that C ++ does not do a good job of "Separating interfaces from implementations. The class definition not only describes the class interface in detail, but also includes full implementation details. For example:
Class perpson {public: STD: string name () const; STD: String birthdata () const; STD: String address () const ;... PRIVATE: STD: String thename; // Implementation Details: Date thebirthdate; address theaddress ;};
At the top of the person definition file, there may be something like this:
#include <string>#include "date.h"#include "address.h"
Unfortunately, a compilation and storage relationship is formed between the person definition file and Its contained files. If either of these header files is changed or other header files are changed, each file containing the person class must be re-compiled. Such dependencies can cause unspeakable disasters to many projects.
Consider adding a pre-declaration to remove the # include header file:
class Date;class Address;
It is difficult for the compiler to know the object size during compilation. Consider this:
int main(){ int x; Person p; ...}
When the compiler sees the definition of X, it knows how much memory must be allocated to hold an int. No problem. Every compiler knows how big an int is. When the compiler sees the definition of P, it also knows that space must be allocated to rotate a person, but how does it know how big a person object is? The only way is to ask the class definition. However, if the class definition can legally not List Implementation Details (using the pre-declaration), how does the compiler know how much space to allocate?
2. Handle class
We can use pimpl to "Hide object implementation details behind a pointer" in the game. We can do this for person: Divide person into two classes, one provides only interfaces, and the other is responsible for implementing this interface. The class to be implemented is named personimpl. The person is defined as follows:
# Include <string> # include <memory> class personimpl; Class date; Class address; class person {public: STD: string name () const ;... PRIVATE: STD: tr1: shared_ptr <personimpl> pimpl; // pointer ,};
The above design is often referred to as pimpl idiom (pimpl is "pointer to implementation"). Classes using pimpl idiom like person are often called handle classes. In this way, the customer of person is completely separated from dates and so on, thus realizing "interface and implementation separation ". The key to this separation is to replace "define dependency" with "declared dependency". In fact, everything comes from these simple design strategies:
1) If you can use object references or object pointers to complete the task, do not use objects.
2) If possible, replace the class definition with the class declaration. Note: When you declare a function and use a class, you do not need the definition of this class. Even if you pass the parameter (or return value) of this type in the by value mode, the same is true:
Class date; // class declarative date today (); // No problem -- the definition of date is not required here. Void clearappointments (date D );
3) provide different header files for declarations and definitions
3. Interface Class
This makes person a special abstract base class called interface class. As follows:
Class person {public: static STD: tr1: shared_ptr <person> Create (); // use a factory method to create a real object virtual ~ Person (); Virtual STD: string name () const = 0; virtual STD: String birthdate () const = 0; virtual STD: String address () const = 0 ;}
class RealPerson: public Person {...}static std::tr1::shared_ptr<Person> create { return std::tr1::shared_prt<Person>(new RealPerson());}
Note: Put the factory method into a separate factory class, and the effect should be better.
From Objective C ++
PS:Pimpl Implementation Method
Pimpl can be implemented in the following ways:
//Person.h#include <memory>class Person{public:Person(void);~Person(void);private:class PersonImpl;std::tr1::shared_ptr<PersonImpl> pImpl;};//Person.cpp#include "Person.h"class Person::PersonImpl {};Person::Person(void){pImpl = std::tr1::shared_ptr<PersonImpl>(new PersonImpl);}Person::~Person(void){}
The personimpl is defined in the person domain and is invisible to the outside.