Effective C + + 34

Source: Internet
Author: User

34. Minimize compilation dependencies between files.

For a large program, its structure is complex, when you make some changes to a class, the modification is not the interface, but the implementation of the class, that is, just a few details, but when the program is regenerated, all the files used in this class will be recompiled. The topic here refers to this meaning. But in fact, I practiced in vs2012, for Class B is associated with Class A, the implementation of Class B depends on Class A, if the implementation of Class A changes, and does not affect the B, that is, the compiler will only recompile a when generated, and for the user program dependent on a, and will not be as it says all recompile. Well, I'm finally getting to the point where what it says changes its implementation.

Modify the implementation of the class: the interface of the class is just the function provided to the outside class, and the implementation of the class refers to the internal logic and data structures required by the class to implement the interface functions, such as some private functions, and some private member data. To modify the implementation of these classes, the declaration of the function must be modified for the implementation of the function, and the modification of the data member is the type of the data member and the number of modifications. When these modifications are made, it is bound to cause the user program that called the class to recompile.

The general solution is to separate the implementation from the interface, that is, for a class to be used, it is converted to two classes, a class is an interface class for the user program invocation, a class for the implementation of the class, there are specific implementation logic and implementation of the required data members, and the interface class can point to the corresponding implementation class, Changes to the implementation logic do not affect the user program, because the user program only connects to the interface class, and hides the effect of implementing the logical modification, which needs to be recompiled only if the interface changes. The key to separation is that the dependency on the class definition is replaced by a dependency on the class declaration, which reduces the compilation dependency, and the task that provides the class definition, the # include directive, is forwarded to the user file containing the function call by the original function declaration header file.

That is, do not include other header files in the header file, unless they are missing can not be compiled, and one by one to declare the required class, let the user using this header file to include these header files by include, so that user code through the compilation.

The implementation of this interface and implementation separation, in C + + generally there are two methods, one is to hide the implementation of an object behind the pointer, that is, a pointer to an indeterminate implementation. Such a class is called a handle class or an envelope class. The implementation class that is pointed to is called the principal class or the letter class. The handle class, where the interface simply transfers all function calls to the corresponding principal class, has a theme class that implements the class to really do the work. In the interface to convert the data members of the original implementation to functions, and to invoke the data members in the implementation class to implement the function, that is, the interface uses functions to implement the implementation of the data members in the class to pass and return.

If a simple implementation of two classes, a, B,c,a put a int,b in a doubel,c to put the sum of the two, write the code as follows:

ClassA.h:

#pragma onceclass classa{public:public:int A; ClassA (int x) {a = x;} ClassA () {a = 0;} int Geta () const{return A;};
ClassB.h:

Class classb{public:double b;double Getb () Const{return b;} ClassB (double x) {b = x;} ClassB () {b = 0;}};
ClassC.h, i.e. interface:

This header file is called the interface, so that the interface and implementation after the separation, only modify the interface, it will cause the user program to use the interface recompile class classa;//only declared, in the interface as long as they know there are these classes, and in the implementation of the include these header file class Classb;class classcimpl;class classc{public:classc (const classa& xa,const classb& XB); virtual ~ClassC (); int The Geta () const;//function returns the data members in the implementation class double Getb () const;double GetC () Const;private:classcimpl *impl;//using pointers to the implementation class//int aaa;/ /any modification in the interface, it is necessary to recompile its user program};
ClassC.cpp, an interface function, is called to return a function in the implementation class.

Here is also the implementation of the interface, modify the data here, will not cause other programs to recompile # include "ClassC.h"//This is the interface ClassC function implementation of the concrete # include "ClassCImpl.h"//To include the implementation of the definition of the class, And the implementation class has the same member function as ClassC in CLASSC::CLASSC (const classa& xa,const classb& XB) {impl = new Classcimpl (XA,XB);} CLASSC::~CLASSC () {delete impl;} int Classc::geta () Const{return Impl->geta ();} Double  Classc::getb () Const{return Impl->getb ();} Double  classc::getc () Const{return impl->getc ();}
Classcimpl, the definition of the implementation class:

#include "ClassA.h" #include "ClassB.h" class Classcimpl{public:classcimpl (const classa& xa,const classb& XB); the int geta () const;//function implements the interface in the function double Getb () const;double GetC () Const;private:classa A; ClassB B; ClassB C;};
ClassCImpl.cpp, the simple operation of implementing a class:

#include "ClassCImpl.h"//To include the definition of the implementation class, and the implementation class has the same member function as in CLASSC classcimpl::classcimpl (const classa& Xa,const ClassB & XB) {A = XA; B = XB; C = (B.GETB () + A.geta ());} int Classcimpl::geta () Const{return A.geta ();} Double  Classcimpl::getb () Const{return B.getb ();} Double  classcimpl::getc () Const{return C.getb ();}
In this way, the interface and implementation are separated, the interface is defined in the CLASSC, and in the case of the interface is fixed, the compiler will only recompile the implementation class, but not all recompile, if it can be modified in the interface implementation class Classcimpl. This is a separation of the interfaces implemented with the handle class from the implementation.

Another method becomes the Protocol class, that is, the class becomes a special type of abstract base class. The Protocol class simply determines the interface for the derived class, which has no data members, no constructors, a virtual destructor, and some pure virtual functions that make up the interface.
The user of the Protocol class creates a new object through a function similar to a constructor, and the class in which the constructor resides is a derived class that is hidden behind. This function, commonly called a factory function, returns a pointer to a dynamically allocated object that supports the derived class of the Protocol class interface. This factory function is associated with decryption of the Protocol class, so it is generally declared as a static member of the Protocol class. If you re-declare a CLASSD, complete the previous function, but for a protocol class, there are:

ClassD.h:

This is only declared for the Protocol class classa;//, in the interface as long as they know that there are these classes, and in the implementation only go to include these header files class Classb;class classd{public:virtual ~CLASSD () {} virtual int Geta () const = 0;//function to return data members in the implementation class virtual Double Getb () const = 0;virtual double getd () const = 0;static CLASSD * MAKECLASSD (const classa& xa,const classb& XB);//use static member to return};
Then write a derived class to implement the CLASSD function, RealClassD.h:

#include "ClassA.h" #include "ClassB.h" #include "ClassD.h" Class Realclassd:public CLASSD{PUBLIC:REALCLASSD (const classa& xa,const classb& XB): A (XA), B (XB), D (B.GETB () + A.geta ()) {}virtual ~realclassd () {} int geta () const; Double Getb () const; Double getd () Const;private:classa A; ClassB B; ClassB D;};
In this derived class definition, incidentally, the MAKECLASSD function that returns a pointer in CLASSD is implemented. Here: The interface specification is inherited from the Protocol class, and then the functions in the interface are implemented in the implementation.

#include "RealClassD.h" int Realclassd::geta () Const{return A.geta ();} Double Realclassd::getb () Const{return B.getb ();}; Double realclassd::getd () Const{return D.getb ();} classd* CLASSD::MAKECLASSD (const classa& xa,const classb& XB) {return new REALCLASSD (XA,XB);}

And where it's needed, so call this function to point to the desired interface:

classd* dd = CLASSD::MAKECLASSD (A, b); cout<<dd->getd () <<endl;
The pointer of DD is dynamically bound to the returned derived class object, and the members whose implementation is modified in the derived class simply recompile the derived class's CPP.


The handle class and the protocol class separate the interface and the implementation, thus reducing the dependencies between files, when there is a certain amount of time and space consumption. When a program is turned into a product, a specific class is used to replace the handle class and the Protocol class.


Effective C + + 34

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.