C + + minimizes the compilation dependencies between files---effective C + + __c++

Source: Internet
Author: User
Tags class definition
clause 31: Minimizing compilation dependencies between files

questions raised: If we make some changes to the implementation of a class, the modification is not the interface of class, but the implementation part, and only the private part is changed, then the whole file is rebuilt, but when you compile it, you can find that the class is recompiled and linked. What the heck...

The reason for this is that C + + does not "detach the interface from the implementation." The section does well, class forms include not only interfaces, but also full implementation projects, such as:

Class person{public
: Person
    (const std::string& name,const date& birthday,const address&);
    std::string name () const;
    std::string birthdate () const;
    std::string address () const;
    ...
Private:
    std::string thename;//Implementation Breakdown
    Date thebirthdate;//Implementation Breakdown address
    theaddress;//implementation details
};  

The class person here cannot be compiled because this file contains the definition of class date,address and string, and such a definition is usually provided through the #include indicator. The above typically includes the following code:

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

This creates a "compile dependency" between the person definition file and the import file, and if any of the header files are changed, or if any other headers in the header file are changed, then each file containing the person class needs to be recompiled, with any Class files also need to be recompiled, so a string compilation dependency will make the entire project Super complex and easily crash.

Since this is a big problem, why C + + insists on implementing a breakdown of class to the class definition. Why not define person so that the implementation details are described separately ... The code is as follows:

Namespace std{
    class string;
Class Date;
class address;
Class person{public
: Person
    (const std::string& name,const date& birthday,const address&);
    std::string name () const;
    std::string birthdate () const;
    std::string address () const;
    ...

There will be two problems with this implementation:
1 string is not class, it is just basic_string, so a predecessor statement for the string above is not clear, and the correct predecessor statement is complicated because it is not important to design additional templates;
2 The compiler needs to know the size of the object during compilation.
See how C + + solves this problem.

#include <string>
#include <memory>//This is included for trl::shared_ptr;
class Personimpl;
Class Date;
class address;

Class person{public
: Person
    (const std::string& name,const date& birthday,const address&);
    std::string name () const;
    std::string birthdate () const;
    std::string address () const;
    ...
Private:
    std::trl::shared_ptr<personimpl> pimpl;//Pointer, pointing to the Implementation object

You can see that the main class contains only one pointer member, pointing to its implementation class, so the design is often called Pimpl idiom, and the pointers in this class are often pimpl, like the code above. In this design, the client of person is completely separated from the date,address and the implementation details of the person.
* * The key to this separation is the substitution of "declarative dependencies" with "defined dependencies", which is the essence of compiler dependencies minimization,

* * Reality makes the header file as satisfying as possible, and if it doesn't, it depends on the declaration (and not the definition) in the other file, and everything else comes from this simple design strategy:
1 If you are using object references or object pointers to complete the task, do not use object, you can define the references and pointers that point to that type by just one type declaration. But if you define a type of objects, you need to use that type of definition;
2 If you can, try to replace the class definition with the class declaration, note that when you declare a function and it is used in a class, you do not need the definition of class;
3 provides a different header file for declarative and defined types.

Using Pimpl idiom class like person is often called handle classes, then how to implement a member function in person. There are two kinds of answers:

1 It is of course to use PERSONIMPL implementation of the implementation of the function of the class.

#include "Person.h"
#include "PersonImpl.h" person
::P erson (const std::string& Name,const date& Birthday,const address& addr):p Impl (New Personimpl (NAME,BIRTHDAY,ADDR))
{} ...
std::string person::name () const{return
    pimpl->name ();
}

Notice here that the person constructor, Personimpl, invokes the constructor of the Person::name function and calls Personimpl::name, so that the person becomes a handle class and does not change what it does. will only change the way it works.
2 makes person a special abstract base class (abstract base class), called interface class, whose purpose is to detail one by one to describe the interface of derived classes, so it usually takes no member variables, There are no constructors, just a series of virtual functions and a virtual destructor, and we can usually design a factory factory function or virtual constructor for implementation, such as:

class person{public:virtual ~person ();
    Virtual std::string name () const=0;
    Virtual std::string birthdate () const=0;
    Virtual std::string address () cosnt=0;
...
}; Class Realperson:public person{Public:realperson (const std::string& name,const date& Address & addr): thename (name), Thebirthdate (birthday), theaddress (addr) {} virtual ~realperson () {} std::string name (
    ) const;
    std::string birthdate () const;
std::string address () const;
    Private:std::string thename;
    Date thebirthdate;
Address theaddress;
}; Class person{public: ... static std::trl::shared_ptr<person> create (const std::string& Name,const date& Amp
    Birthday,const address& addr); ...
};

For handle classes, the member function must obtain the object's data through implementation pointer, which adds a layer of indirection to each visit. Each object small number of memory must increase implementation pointer size, finally impementation pointer must initialize, point to a dynamically allocated implementation object, So you need to experience the overhead of dynamic memory allocation (and its subsequent release), and the likelihood of bad_alloc having mercy flights;
For interface classes, each function is virtual, so you have to pay an indirect jump cost for each function call, and the interface class derivation must contain a vptr, This only hate may increase the amount of memory needed to store the object.

Summarize:
1 The general method of supporting "compiling dependency minimization" is to rely on the statement-style, do not rely on the definition, two methods based on handle are classes and interface classes.
2 The library header file should be in the form of "complete and only declarative", a practice that can be applied whether or not design templates.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.