"C++ Primer Plus" Reading Notes Eleven - Class Inheritance

Chapter 13 Class Inheritance

  1. Class inheritance : extending and modifying classes.

  2. Public inheritance format: The colon indicates that the base class of class B is A, and B is the derived class.

  class B :public A

  {

    。。。

  };

  3. The derived class object contains the base class object. With public derivation, the public members of the base class will become public members of the derived class; the private parts of the base class will also become part of the derived class, but can only be accessed through the public and protected methods of the base class. The derived class object stores the data members of the base class (the derived class inherits the implementation of the base class); the derived class object can use the methods of the base class (the derived class inherits the interface of the base class).

  4. What needs to be added to the inheritance feature? First, derived classes need their own constructors. The derived class can then add additional data members and member functions as needed.

  5. The constructor of the derived class must provide data to new members (if any) and inherited members. However, derived classes cannot directly access the private members of the base class, but must do so through methods of the base class . Specifically, the derived class constructor must use the base class constructor.

  6. When creating a derived class object, the program first creates the base class object. This means that the base class object should be created before the program enters the derived class constructor. C++ uses member initialization list syntax to do this. For example, here is a constructor for a derived class B : where A(fn,ln,ht) is the member initialization list.

  B::B(int r,const char *fn,const char *ln,bool ht):A(fn,ln,ht) // (fn,ln,ht) is the base class private data member

  {

    rating =r; // rating is a derived class member

  }

  What if the member initialization list is omitted ?

  B::B(int r,const char *fn,const char *ln,bool ht) // (fn, ln, ht) are base class private data members

  {

    rating =r; // rating is a derived class member

  }

  The base class object must be created first, if the base class constructor is not called, the program will use the default base class constructor , so the above code is equivalent to the following:

  B::B(int r,const char *fn,const char *ln,bool ht):A() // (fn, ln, ht) are base class private data members

  {

    rating =r; // rating is a derived class member

  }

  Note: Unless the default constructor is to be used, the correct base class constructor should be called explicitly.

  7. Let's look at the constructor of the second derived class B:  because the type of tp is const A &, the copy constructor of the base class will be called. If you need to use a copy constructor and don't define it, the compiler will automatically generate one.

  B::B(int r,const A & tp):A(tp) 

  {

    rating =r; // rating is a derived class member

  }

  8. If you prefer, you can also use member initialization list syntax for derived class members.

  9. Remember: When creating a derived class object, the program first calls the base class constructor, and then calls the derived class constructor. The base class constructor is responsible for initializing the inherited data members; the derived class constructor is mainly used to initialize the newly added data members. A constructor of a derived class always calls a constructor of a base class. A member initialization list can be used to indicate which base class constructor to use, otherwise the default base class constructor will be used. When a derived class object expires, the program will call the derived class destructor first, and then call the base class destructor.

  10. The special relationship between the derived class and the base class : 1. The derived class object can use the method of the base class (in the same way as the base class object calls the method), provided that the method is not private. Second, the base class pointer can point to the derived class object without explicit type conversion; the base class reference can refer to the derived class object without explicit type conversion. However, base class pointers or references can only be used to call base class methods. Note: Base class objects and addresses cannot be assigned to derived class references and pointers.

  11. For a function, if its formal parameter is a base class reference, you can use the base class object or the derived class object as an actual parameter.

    For a function, if its formal parameter is a pointer to the base class, you can use the address of the base class object or the address of the derived class object as an argument.

  12. The reference compatibility attribute can also initialize a base class object to a derived class object, although less directly . as follows:

  B b=(1840,"abc","def",true);// Derived class object

  A a(b); // Initialize base class object with derived class object

  To initialize a, the matching constructor prototype is: A (const B &); There is no such constructor in the class, but an implicit copy constructor exists : A (const A &); The formal parameter is a base class reference, so it Derived classes can be referenced. The implicit constructor initializes a to an A object nested within a B object b.

  13. Similarly, the derived class object can also be assigned to the base class object :

  B b=(1840,"abc","def",true);// Derived class object

  A a; 

  a=b; // assign the base class object with the derived class object

 

   In this case, the program will use the implicit overloaded assignment operator :

  A & operator = (const A &) const; the base class reference also points to the derived class object, so the base class part of b is copied to a.

  14. C++ has three inheritance methods : public inheritance, protected inheritance and private inheritance. Public inheritance is the most commonly used, it establishes an is-a relationship , that is, the derived class object is also a base class object, and any operation that can be performed on the base class object can also be performed on the derived class object.

  15. The behavior of a class method should depend on the object on which the method is called. This more complex behavior is called polymorphism - having multiple shapes, meaning that the same method will behave differently depending on the context. There are two important mechanisms that can be used to achieve polymorphic public inheritance : 1. Redefine the methods of the base class in the derived class. ② Use virtual methods.

  16. For methods that behave the same in both classes, declare them only in the base class.

  17. If the keyword virtual is not used in the base class method , the program will select the method according to the reference type or pointer type; if virtual is used, the program will select the method according to the type of the object pointed to by the reference or pointer.

  18. The method that the derived class will redefine is often declared as a virtual method in the base class. After a method is declared virtual in the base class, it will automatically become virtual in the derived class.

  19. In a derived class method, the standard technique is to use the scope resolution operator to call the base class method.

  20. You can create an array of pointers to the base class, then the pointers in the array can point to both the base class object and the derived class object, so you can use an array to represent multiple types of objects, which is polymorphism! !

  21. Why is virtual destructor needed? If the destructor is not virtual, only the destructor corresponding to the pointer type will be called. If the destructor is virtual, the destructor for the corresponding object type will be called. Therefore, using virtual destructors ensures that the correct sequence of destructors is called.

  22. Static Binding (Early Binding): The compiler is responsible for answering which executable code block will be used when the program calls a function. Interpreting a function call in source code as executing a specific block of function code is called function name binding. In C++, because of function overloading, the compiler must look at the function parameters and the function name to determine which function to use. However, C++ compilers can do this during compilation. Binding during compilation is called static binding. Dynamic binding (late binding): Which function to use cannot be determined at compile time, the compiler must generate code that can select the correct virtual method at program runtime, which is called dynamic binding.

  23. Converting a derived class reference or pointer to a base class reference or pointer is called an upcast , which makes public inheritance without explicit type conversion. as follows:

  B b=(1840,"abc","def",true);// Derived class object

 

  A *a=&b; // A &a=b;

  Converting a base class pointer or reference to a derived class pointer or reference is called a downcast , and downcasting is not allowed without using an explicit typecast.

  A a; // base class

  B b; // derived class

  A *a=&b;

  B *b=(B *)&a;

  24. Remember: the derived class object is the base class object, because it inherits all the data members and member functions of the base class object. Therefore, operations that can be performed on objects of the base class apply to objects of the derived class.

  25. The compiler uses static binding for non-virtual methods and dynamic binding for virtual methods.

  26. If the class will not be used as a base class, dynamic binding is not required. Likewise, if the derived class does not redefine any methods of the base class, dynamic binding is not required. In these cases, it is more reasonable and efficient to use static binding. Therefore, static binding is set as the default choice for C++.

  27. How virtual functions work: add a hidden member to each object. The hidden member holds a pointer to an array of function addresses. Such an array is called a virtual function table (vtbl). The virtual table stores the addresses of virtual functions declared for class objects. The base class object contains a pointer to the address table of all virtual functions in the base class. The derived class object will contain a pointer to a separate address table. If a derived class provides a new definition of a virtual function, the virtual function will hold the address of the new function. If the derived class does not redefine the virtual function, this vtbl will hold the definition of the original version of the function. If the derived class redefines a new virtual function, the address of that function will also be added to vtbl. Note: No matter whether the virtual function contained in the class is one or 10, only one address member needs to be added to the object, but the size of the table is different.

  28. The cost of using virtual function memory and execution speed: ① Each object will increase, and the increase is the space for storage addresses. ② For each class, the compiler creates a virtual function address table (array). ③ Each function call needs to be performed without additional operations, that is, to look up the address in the table.

  29. A constructor cannot be a virtual function; a destructor should be a virtual function, unless the class is not used as a base class; a friend cannot be a virtual function, because a friend is not a class member, and only a class member can be a virtual function.

  30. If the derived class does not redefine the function, the base class version of the function will be used. If the derived class is in the derivation chain, the latest virtual function version will be used, with the exception that the base class version is hidden.

  31. Redefining inherited methods is not overloading. If you redefine a function in a derived class, instead of overriding the base class declaration with the same function signature, the base class method of the same name will be hidden, regardless of the signature.

  32. Two rules of thumb: ① If you redefine an inherited method, you should ensure that it is exactly the same as the original prototype, but if the return type is a base class reference or pointer, you can modify it to a reference or pointer to a derived class. This feature is called return type covariance , because the return type is allowed to vary with the class type. If the base class declaration is overloaded, all the base class versions should be redefined in the derived class. If only one version is redefined, the other two versions will be hidden and derived class objects will not be able to use them. Note that the new definition can just call the base class version if no modification is required.

  33. The difference between private and protected is only manifested in classes derived from the base class. Members of the derived class can directly access the protected members of the base class, but not the private members of the base class. Thus, to the outside world, protected members behave like private members; but to derived classes, protected members behave like public members.

34. C++ provides unimplemented functions   by using pure virtual functions. The end of a pure virtual function declaration is =0. When a class contains a pure virtual function, an object of that class cannot be created, and a class containing a pure virtual function is only used as a base class! ! To be a pure virtual function, it must contain at least one pure virtual function. A pure virtual function may or may not be defined! !

  35. A class derived from an abstract base class (ABC) is called a concrete class. ABC describes an interface that uses at least one pure virtual function, and a class derived from ABC uses regular functions to implement this interface according to the specific characteristics of the derived class. ABC contains all methods and data members common to derived classes, and those methods that behave differently in derived classes should be declared as virtual functions.

  36. Inheritance and dynamic memory allocation: ① Derived classes do not use new: There is no need to define explicit destructors, copy constructors and assignment operators for derived classes. ② Derived classes use new: explicit destructors, copy constructors, and assignment operators must be defined for derived classes. Note: The derived class copy constructor can only access the derived class data, so it must call the base class copy constructor to handle shared base class data.

  37. Summary: When both the base class and the derived class use dynamic memory allocation, the destructor, copy constructor and assignment operator of the derived class must use the corresponding base class methods to deal with the base class elements. This requirement is met in three different ways. For destructors, this is done automatically; for constructors, this is done by calling the base class's copy constructor in the initializing member list; if you don't do this, the base class's default constructor is automatically called. For assignment constructors, this is done by explicitly calling the base class assignment operator using the scope resolution operator.

  38. About friend function: If you want the friend function of the derived class to be able to use the friend function of the base class , you can convert the derived class reference or pointer to the base class reference or pointer by casting, and then use the converted pointer or A reference to call a friend function of the base class.

  39. If a function declares a parameter as a reference or pointer to const, the parameter cannot be passed to another function unless the latter also ensures that the parameter will not be modified.

  40. What cannot be inherited? Constructor, destructor, assignment operator, friend function.

  41. Can a base class object be assigned to a derived class object ? Can! ! Method ① The derived class has a conversion constructor: B (const A &), the conversion constructor can accept a parameter of the base class and other parameters, provided that the other parameters have default values: B (const A & a, double c =1.0,double r=0.1); if there is a conversion function, the program will use it to create a derived class object based on the base class object, and then use it as the parameter of the assignment operator. Method ② Define an assignment operator for assigning a base class to a derived class: B & B::operator=(const A &){...}

   

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325207986&siteId=291194637