当前位置:网站首页>Understand the concepts of virtual base class, virtual function and pure virtual function (turn)

Understand the concepts of virtual base class, virtual function and pure virtual function (turn)

2022-04-23 14:06:00 JokerYourMemory

introduction

     I haven't written a conceptual article for a long time , Because I think these conceptual things are all in books, and they are very detailed. It's useless to write them down , I had a whim to write today Write , Let's discuss the virtual base class 、 Virtual function and pure virtual function , It's easy to feel confused at the sight of the name . But don't worry. After reading this article, you will understand .

Text

       virtual base class
       Look at a piece of code before explaining what it does

class A
{
public:
    int iValue;
};

class B:public A
{
public:
    void bPrintf(){cout<<"This is class B"<<endl;};
};

class C:public A
{
public:
    void cPrintf(){cout<<"This is class C"<<endl;};
};

class D:public B,public C
{
public:
    void dPrintf(){cout<<"This is class D"<<endl;};
};

void main()
{
    D d;
    cout<<d.iValue<<endl; // error , Ambiguous access
    cout<<d.A::iValue<<endl; // correct
    cout<<d.B::iValue<<endl; // correct
    cout<<d.C::iValue<<endl; // correct
}


You can see from the code that the class B C All inherit classes A Of iValue member , So the class B C All have a member variable iValue , And category D And inherited B C, Such kind D There is a member with the same name iValue( One is from the class B Inherited from , One is from the class C Inherited from ). Call in main function d.iValue Because class D There is a member with the same name iValue The compiler does not know the call From whom iValue So there is the problem of ambiguity . The correct approach should be to add the scope qualifier d.B::iValue Indicates that the call is from B Class inherited iValue. however class D There are multiple instances of iValue Example , It takes up memory space . therefore C++ The concept of virtual base class is quoted in , To solve this problem .

class A
{
public:
    int iValue;
};

class B:virtual public A
{
public:
    void bPrintf(){cout<<"This is class B"<<endl;};
};

class C:virtual public A
{
public:
    void cPrintf(){cout<<"This is class C"<<endl;};
};

class D:public B,public C
{
public:
    void dPrintf(){cout<<"This is class D"<<endl;};
};

void main()
{
    D d;
    cout<<d.iValue<<endl; // correct
}


Precede the inherited class with virtual Keyword indicates that the inherited class is a virtual base class , Its inherited member retains only one instance in the derived class . for example iValue This member , From the class D From this point of view , It is from class B With the class C inherited , And category B C From the class A inherited , But they only keep one copy . Therefore, the middle note is called in the main function. d.iValue Not when There will be mistakes . 

       Virtual functions
       Or look at the code first

class A
{
public:
  void funPrint(){cout<<"funPrint of class A"<<endl;};
};

class B:public A
{
public:
    void funPrint(){cout<<"funPrint of class B"<<endl;};
};

void main()
{
    A *p; // Defines a pointer to the base class
    A a;
    B b;
    p=&a;
    p->funPrint();
    p=&b;
    p->funPrint();
}


What do you think the output of this code is ? Some people may answer right away funPrint of class A And funPrint of class B Because the first output is a reference class A Reality of Example ah , The second output is the reference class B It's a good example . Then I tell you it's wrong to think so , The answer is funPrint of class A And funPrint of class A As for why output Such a result is beyond the scope of this paper ; Just remember , No matter which class the referenced instance is, when you call it, the system will call the method of the class to which the lvalue object belongs . for instance The above code class A B There is one. funPrint function , because p It's a A Pointer to class , So whether you're going to p Pointer to class A Or class B, The final functions called are classes A Of funPrint function . This is the static couplet , The compiler has been determined at the time of compilation . But what if I want to dynamically decide which function to call according to different instances ? This requires the use of Virtual functions ( That is, dynamic couplets )

class A
{
public:
    virtual void funPrint(){cout<<"funPrint of class A"<<endl;};
};

class B:public A
{
public:
    virtual void funPrint(){cout<<"funPrint of class B"<<endl;};
};

void main()
{
    A *p; // Defines a pointer to the base class
    A a;
    B b;
    p=&a;
    p->funPrint();
    p=&b;
    p->funPrint();
}


Add before the member function of the base class virtual Keyword indicates that this function is a virtual function , The so-called virtual function is that you are not sure which function to call when compiling , It's a dynamic decision to be adjusted Which function , To implement a virtual function, the function name of the derived class must be the same as that of the base class , Parameter name, parameter type, etc. should also be the same as the base class . But in derived classes virtual Keywords can be omitted , Also table This is an imaginary function . Let's solve the code , Declare a pointer to a base class ( Must be a base class , Not the other way around )p, hold p Pointing class A Example a, call funPrint function , this The system will judge when p The type of instance pointed to , If it is A Class is called A Class funPrint function , If it is B Class is called B Class funPrint function .

     Pure virtual function  

     It's better to call it abstract class than pure virtual function , It simply declares a function but does not implement it , Let derived classes implement it , In fact, it's easy to understand . 

class Vehicle

{
public:
    virtual void PrintTyre()=0; // Pure virtual functions are defined in this way
}
;
class  Camion: public  Vehicle
{
public:
    virtual void PrintTyre(){cout<<"Camion tyre four"<<endl;};
}
;

class  Bike: public  Vehicle
{
public:
    virtual void PrintTyre(){cout<<"Bike tyre two"<<endl;};
}
;

void  main()
{
    Camion c;
    Bike b;
    b.PrintTyre();
    c.PrintTyre();
}


Code above , Defines a vehicle class (Vehicle), There is a function in the class that can print the number of tires of the vehicle , However, the number of tires in many vehicles is naturally uncertain , therefore Just define it as a pure virtual function , That is, just define the function name without implementing it , class Camion Inherited Vehicle And implemented the code inside , Print out 4 A tire .Bike Class is the same . There is one thing that needs attention , Pure virtual functions cannot be realized , However, pointers can be declared .


summary

     virtual base class  
    1, A class can be used as a virtual base class in a family of classes , Also used as a non virtual base class . 
    2, In the object of the derived class , A virtual base class with the same name produces only one virtual base class sub object , A non virtual base class generates its own sub objects . 
    3, Virtual base class sub objects are initialized by the constructor of the most derived class by calling the constructor of the virtual base class . 
    4, The most derived class refers to the class specified when creating an object in the inheritance structure . 
    5, The member initialization list of the constructor of the derived class must list the calls to the virtual base class constructor ; If not listed , It means that the default constructor of the virtual base class is used . 
    6, The member initialization list of the constructor in the derived class directly or indirectly derived from the virtual base class should list the calls to the virtual base class constructor . But only the most derived used to build objects The constructor of class calls the constructor of virtual base class , The calls to the constructor of the virtual base class listed in all base classes of the derived class are ignored in execution , So as to ensure that the virtual base class sub objects Initialize only once . 
    7, When both virtual base class and non virtual base class constructors are called in a member initialization list , The constructor of a virtual base class executes before the constructor of a non virtual base class . 

     Virtual functions  
    1, Virtual functions are non static 、 Non inline member function , Not a friend function , But virtual functions can be declared as friend functions in another class . 
    2, Virtual function declaration can only appear in the function prototype declaration of class definition , It cannot be declared when the function body of the member function is implemented . 
    3, No matter how many times a virtual function is inherited by the public , It still retains the properties of its virtual function . 
    4, If a member function in a class is described as a virtual function , Then the member function may have different implementations in the derived class . When the member function is used to manipulate the object identified by the pointer or reference , Dynamic binding can be adopted for calling this member function . 
    5, After defining the virtual function , The pointer to the base class declared in the program can point to its derived class . In the process of execution , This function can constantly change the object it points to , Different calls Version of member function , And these actions are implemented dynamically at runtime . Virtual functions fully embody the dynamic polymorphism of object-oriented programming . Pure virtual function Version of member function , And these actions are implemented dynamically at runtime . Virtual functions fully embody the dynamic polymorphism of object-oriented programming .

     Pure virtual function  
    1, When a meaningful implementation of a virtual function cannot be given in a base class , You can declare it as a pure virtual function , Its implementation is left to the derived class . 
    2, The function of pure virtual function is to provide a consistent interface for derived classes . 
    3, Pure virtual functions cannot be realized , However, pointers can be declared .

版权声明
本文为[JokerYourMemory]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204231401090972.html