C++ Inheritance | Diamond Inheritance and Virtual Inheritance | Some written interview questions about inheritance

Article directory

1. The concept and definition of inheritance

1. Inheritance definition

2. Inheritance relationship and access qualifiers

2. Assignment and conversion of base class and derived class objects

3. Scope in inheritance

4. Default member functions of derived classes

5. Inheritance and Friendship

6. Inheritance and static members

7. Complex diamond inheritance and diamond virtual inheritance

Diamond inheritance: Diamond inheritance is a special case of multiple inheritance.

Solve the problem of diamond inheritance: virtual inheritance

8. Summary of inheritance

9. Written interview questions about inheritance

Summarize



1. The concept and definition of inheritance

The inheritance mechanism is the most important means of object-oriented programming to make code reusable. It allows programmers to extend and add functions while maintaining the original characteristics , thus generating new classes called derived classes . Inheritance presents the hierarchical structure of object-oriented programming and reflects the cognitive process from simple to complex. Inheritance is the reuse of class design levels .

//基类 person
class Person
{
    public:
        void Print()
        {
            cout<<"name:" <<_name<<endl;
            cout<<"age:"<<_age<<endl;
        }


    protected:
        string _name = "peter";
        int _age;
};


class Student::Person
{
    protectd:
        int _stuid; //学号;
};

int main()
{
    Student s;
    s.print();
    return 0;
}

1. Inheritance definition

class Student::public Person 

2. Inheritance relationship and access qualifiers

Inheritance methods are divided into: public inheritance, protected inheritance, and private inheritance.

Access qualifiers: public access, protected access, private access

Class members/inheritance methods public inheritance protected inheritance private inheritance
Public members of the base class public members of derived classes protected members of derived classes Private members of derived classes
Protected members of the base class protected members of derived classes protected members of derived classes Private members of derived classes
private members of base class Not visible in derived classes Not visible in derived classes Not visible in derived classes

Summarize:

  1. The private members of the base class are invisible in the derived class no matter how they are inherited. The invisible here means that the private members of the base class are still inherited into the derived class object, but the syntax restricts the derived class object within the class. Or cannot be accessed outside the class
  2. Private members of the base class cannot be accessed in the derived class. If the base class member does not want to be directly accessed outside the class, but needs to be accessed in the derived class, it is defined as protected. It can be seen that the protected member qualifier appears because of inheritance .
  3. When using the keyword class, the default inheritance method is private , and when using struct, the default inheritance method is Public . It is best to write out the inheritance method explicitly.
  4. The most commonly used method in practice is public inheritance.

2. Assignment and conversion of base class and derived class objects

  • Derived class objects can be assigned to base class objects/base class pointers/base class references. This is called slicing or cutting. This means that the part of the parent class in the derived class is assigned the value.
  • Base class objects cannot be assigned to derived class objects
  • A base class pointer or reference can be assigned to a derived class pointer or reference through forced type conversion, but it is safe only when the base class pointer points to a derived class object. If the base class is a polymorphic type, you can use RTTI's dynamic_cast to identify it and perform safe conversion.

3. Scope in inheritance

  • In the inheritance system, base classes and derived classes have independent scopes.
  • If there are members with the same name in the subclass and the parent class, the subclass members will block the parent class from direct access to the members with the same name. This situation is called hiding, also called redefinition)
  • If it is the hiding of a member function, only the function names need to be the same to constitute hiding.
  • In practice it is better not to use members with the same name

4. Default member functions of derived classes

The default member function is not written by the programmer, and the compiler will automatically generate it. The six default member functions are:

Initialization and cleanup: The constructor completes the initialization work, and the destructor completes the cleanup work.

Copy assignment: Copy construction uses similar objects to initialize and create objects. Assignment overloading mainly assigns one object to another object.

Address overloading: mainly for ordinary objects and const objects to obtain addresses, which is rarely implemented by oneself.

  1. The constructor of the derived class must call the constructor of the base class to initialize those members of the base class. If the base class does not have a default constructor, it must be explicitly called during the initialization list stage of the derived class constructor.
  2. The copy constructor of the derived class must call the copy constructor of the base class to complete the copy initialization of the base class.
  3. The operator of the derived class = must call the operator of the base class = to complete the assignment of the base class
  4. I am afraid that the destructor of the derived class will automatically call the destructor of the base class to clean up the base class members after being called. Ensure that the derived class object cleans up the derived class members first and then cleans up the base class members.
  5. When initializing a derived class object, first call the base class constructor and then the derived class constructor.
  6. When destructing a derived class object, first call the derived class destructor and then call the base class destructor.
  7. The destructor needs to be rewritten, and one of the conditions for rewriting is that the function name is the same. The compiler will perform special processing on the destructor name and treat it as a destructor. Therefore, when the parent class destructor does not add virtual, the child class destructor and the parent class destructor form a hidden relationship.

5. Inheritance and Friendship

Friend relationships cannot be inherited, which means that base class friends cannot access private and protected members of subclasses.

6. Inheritance and static members

If the base class defines static members, there will be only one such member in the entire inheritance system. No matter how many subclasses are derived, there will be only one static member instance.

class Person
{
public :
 Person () {++ _count ;}
protected :
 string _name ; // 姓名
public :
 static int _count; // 统计人的个数。
};

int Person :: _count = 0;


class Student : public Person
{
protected :
 int _stuNum ; // 学号
};


class Graduate : public Student
{
protected :
 string _seminarCourse ; // 研究科目
};


void TestPerson()
{
 Student s1 ;
 Student s2 ;
 Student s3 ;
 Graduate s4 ;
 cout <<" 人数 :"<< Person ::_count << endl;  //4

}

7. Complex diamond inheritance and diamond virtual inheritance

Single inheritance: A subclass has only one direct parent class. This inheritance relationship is called single inheritance.

Multiple inheritance: A subclass has two or more parent classes. This inheritance relationship is called multiple inheritance.

Diamond inheritance: Diamond inheritance is a special case of multiple inheritance.

Problems with diamond inheritance: From the object member model construction below, we can see that diamond inheritance has data redundancy and ambiguity problems. There will be two copies of the person member variable in the assisttant object.

class person
{
    public:
        string _name;
};


class Student:public person
{
    protected:
        int _num;
};

class Teacher:public person
{
    protectd: 
        int _id;
};

class Assisstant:public Stduent,public Teacher
{
    protected:
        string _majorCourse;
};

void Test()
{
    a._name = "peer" ; //数据的二义性,不知是student还是teacher的_name
    //解决数据的二义性
    a.Student::_name = "p1";
    a._Teacher::_name = "p2";
    //虽然解决了数据的二义性,使用作用域限定符,但是这样带来了数据冗余的问题,数据冗余的本质是空间浪费
}
class A
{

public:
 int _a;
};
// class B : public A
class B :  public A
{
public:
 int _b;
};
// class C : public A
class C : public A
{
public:
 int _c;
};
class D : public B, public C
{
public:
 int _d;
};
int main()
{
 D d;
 d.B::_a = 1;
 d.C::_a = 2;
 d._b = 3;
 d._c = 4;
 d._d = 5;
 return 0;
}

Use the memory window to observe:

Solve the problem of diamond inheritance: virtual inheritance

Virtual inheritance solves the problems of data redundancy and ambiguity. It uses a pointer to store an address, and the offset is stored in this address.

class A
{

public:
 int _a;
};
// class B : public A
class B : virtual public A
{
public:
 int _b;
};
// class C : public A
class C : virtual public A
{
public:
 int _c;
};
class D : public B, public C
{
public:
 int _d;
};
int main()
{
 D d;
 d.B::_a = 1;
 d.C::_a = 2;
 d._b = 3;
 d._c = 4;
 d._d = 5;
 return 0;
}
In the D object, A is placed at the bottom . This A belongs to both B and C. So how do B and C find the common A ? Here is a table pointed to by the two pointers B and C. These two pointers are called virtual base table pointers, and these two tables are called virtual base tables. The offset stored in the virtual base table. A below can be found by the offset.

8. Inheritance and combination

1. Inheritance and composition

//A和B  继承
class A {};

class B:public A
{};

//C和D 组合
class C
{
    public:
        void fun()
        {}
    protected:
        int _a1;
        int _a2;
};

class D
{
  private: 
        C _cc;
}
  • Public inheritance is an is-a relationship, which means that each derived class object is a base class object.
  • Combination is a has-a relationship. Suppose B combines A. Each B object has an A object.
  • Prefer object composition over class inheritance.
  • Inheritance has a higher degree of coupling. B can directly use members of A, and D can directly use a member function of C and indirectly use the other two members. If a member in A is modified, all members in B will be modified. C changes members, and D only needs to change the members it uses.

9. Written interview questions about inheritance

1. What is diamond inheritance and what are the problems with diamond inheritance?

There are single inheritance and multiple inheritance in inheritance. Diamond inheritance is a type of multiple inheritance. The problem of diamond inheritance will lead to ambiguity and redundancy of data.

2. What is diamond virtual inheritance and how to solve redundancy and ambiguity?

Diamond virtual inheritance is to add virtual to the syntax during inheritance. Through virtual inheritance, a pointer is added. This pointer is the address of the virtual base table. Find the offset through the address and then find the public member.

3. The difference between inheritance and combination, when to use inheritance and when to use combination


Guess you like

Origin blog.csdn.net/jolly0514/article/details/132131191