The art of template and inheritance-optimization of null base and template inheritance Art
1. Concept C ++ has the concept of "null" class, which means that it does not have any internal memory during runtime. Classes that only contain type member functions, non-virtual member functions, and static data members are empty classes. Non-static data members, virtual functions and virtual base classes consume storage space during runtime. 2. Optimization of the null base class: # include <iostream> using namespace std; class Empty {typedef int ;}; class EmptyToo: public Empty {}; class EmptyThree: public EmptyToo {}; int main () {cout <"sizeof (Empty):" <sizeof (Empty) <endl; cout <"sizeof (EmptyToo ): "<sizeof (EmptyToo) <endl; cout <" sizeof (EmptyThree): "<sizeof (EmptyThree) <endl ;}( 1) in class EmptyToo, class Empty does not allocate storage space (2) Empty class with optimized null base class as the inherited base class (If there are no other basic classes. 3. If there are other basic classes: # include <iostream> class Empty {typedef int Int ;}; class EmptyToo: public Empty {}; class EmptyThree: public Empty, public EmptyToo {}; int main () {cout <"sizeof (Empty):" <sizeof (Empty) <endl; // output 1 cout <"sizeof (EmptyToo)" <sizeof (EmptyToo) <endl; // output 1 cout <"sizeof (EmptyThree ): "<sizeof (EmptyThree) <endl; // output 2} if the inheritance is multiple inheritance: EmptyThree has two different subclass Empty objects, one is the Empty object inherited directly, and the other Is the Empty object inherited by EmptyToo. Because they are two objects, they cannot have the same address space. Optimization (2) does not work here. EmptyThree is the sum of two Empty and EmptyToo sizes. 4. Take the member as the base class for example. The template parameter will be instantiated as a type (not a non-type, not a native type such as int), and another member type of the template class is not an empty class. Template <typename CustomClass> class Optimizable {private: CustomClass info; void * storage;}; changed to template <typename CustomClass> class Optimizable {private: BaseMemberPair <CustomClass, void *> info_and_storage;}; // template <typename Base, typename Member> class BaseMemberPair: private Base {private: Member member; public: BaseMemberPair (Base const & B, member const & m): Base (B), member (m ){}// Use first to access basic dataBase const & first () const {return (Base const &) * this;} Base & first () const {return (Base &) * this ;}// Use second () to access member variablesMember const & second () const {return this-> member;} Member & second () const {return this-> member ;}}; before optimization: # include <iostream> using namespace std; template <typename CustomClass> class Optimizable {private: CustomClass info; void * storage ;}; class Test {}; int main () {cout <sizeof (Optimizable <Test>) <endl; // The result is 8 return 0 ;}View Code
After optimization:
# Include <iostream> using namespace std; template <typename Base, typename Member> class BaseMemberPair: private Base {private: Member member; public: BaseMemberPair (Base const & B, member const & m): Base (B), member (m) {}// use first to access Base-class data Base const & first () const {return (Base const &) * this;} // provided to the const object to call Base & first () {return (Base &) * this;} // use second () to access the Member variable member const & second () const {return this-> Member;} member & second () {return this-> Member ;}}; template <typename CustomClass> class Optimizable {private: BaseMemberPair <CustomClass, void *> info_and_storage ;}; class Test {}; int main () {cout <sizeof (Optimizable <Test>) <endl; // The result is 4 return 0 ;}View Code
5. Warning:
Template <typename T1, typename T2> class MyClass {private: T1 a; T2 B ;}; // optimize template <typename T1, typename T2> class MyClass: private T1, private T2 {}; if you do not know whether T1 and T2 are of the type, it is best not to blindly use the above optimization method because: (1) this method is not applicable to native types such as int (2) if T1 and T2 are of the same type, there will be problems with inheritance. (3) adding a Base class will change the interface, because multiple inheritance occurs. If both T1 and T2 share a Base class, data members in MyClass will, the member functions will have ambiguity. Therefore, it is best to adapt this method to the situations described previously. Edit: Claruarius. For more information, see the source.