virtual Function Pure virtual Function virtual Base Class in C++.

Keywords: C++


Foreword: To understand the differences among the three, three essential conditions for polymorphism must be mastered:

  1. inherit
  2. heavy load
  3. The parent pointer points to the child class object.

Virtual function pure virtual function virtual base class

1. virtual functions are used to modify parent functions in polymorphisms to ensure that subclass functions run when the parent pointer calls a subclass object.
2. Pure virtual functions are used to define interfaces, that is, to define a purely virtual function in a base class. The base class does not need to be implemented, but subclasses do.
3. Virtual base classes are used in multiple inheritance, such as diamond inheritance, where two parent classes inherit from the same class and only one parent is instantiated

1. Virtual Functions
The first is the general implementation without polymorphism (inheritance only):

class A  
{  
public:  
    void printf(){  
        cout<<"printf A"<<endl;  
    }  
};  
class B : public A  
{  
public:  
    void printf(){  
        cout<<"printf B"<<endl;  
    }  
};  
int main(int argc, const char * argv[])  
{  
    A *a = new A();  
    a->printf();  
    B *b = new B();  
    b->printf();  
    return 0;  
}  

Result:

printf A
printf B

This was code that had no polymorphism in its early stages, with the disadvantage of code redundancy
The following are the cases where polymorphism is used but virtual keywords are not referenced:

int main(int argc, const char * argv[])  
{  
    A *a = new B();  
    a->printf();  
    return 0;  
}  

Result:

printf A

Because the definitions of the classes are the same, they are not written out anymore. If the parent pointer points to the subclass object, the parent calls its own method when it does not use virtual, and there is no method that calls the subclass override, so there is no effect of polymorphism. Let's try adding the virtual keyword to the parent again to see:

class A  
{  
public:  
virtual void printf(){  
        cout<<"printf A"<<endl;  
    }  
};  
class B : public A  
{  
public:  
//Subclasses can also be written directly as void printf() without using virtual
    virtual void printf(){  
        cout<<"printf B"<<endl;  
    }  
};  
int main(int argc, const char * argv[])  
{  
    A *a = new B();  
    a->printf();  
    return 0;  
}  

Result

printf B

Viral is added to the parent class, and the code of the subclass can be as virtual as possible (to facilitate the polymorphism of the inherited subclass) or not. The main function or the parent pointer points to the subclass object, and the result can be printed to the method of the subclass override, so it is confirmed that the virtual function is a function used to modify the override of the parent class in polymorphism, ensuring that the parent pointer calls the subclass pairRunning subclass functions like.
(2) Pure virtual functions
Pure virtual functions are abstract interfaces. Classes that use pure virtual functions cannot be instantiated. Classes that define pure virtual functions need not write implementations of pure virtual functions. They are implemented by subclasses. See the code below:

class A  
{  
public:  
    virtual void printf() =0;  
};  
void A::printf()//Pure virtual functions can be implemented without writing  
{  
    cout<<"printf A"<<endl;  
}  
class B : public A  
{  
public:  
    void printf(){  
        cout<<"printf B"<<endl;  
    }  
};  
int main(int argc, const char * argv[])  
{  
    A *a =new A();//Compilation error, class of pure virtual function cannot be instantiated  
    a->printf();  
    return 0;  
}  

virtual void printf() = 0; this is the way to write virtual functions. I have written below the implementation of virtual functions void A::printf(), which does not matter if written or does not work. Then I try to instantiate the class of pure virtual functions in main function, and the result is directly wrong, indicating that pure virtual functions cannot be instantiated.

int main(int argc, const char * argv[])  
{  
    A *a =newB();//Polymorphism is used here  
    a->printf();  
    return 0;  
}  

Result:

printf B

Pointing a of the main function to an object of a subclass will print the method of the subclass correctly.This shows that pure virtual functions are also polymorphic services, and their function is to define an interface for subclasses to implement.
(3) Virtual base classes
Virtual base classes are unique to c++, because there is much inheritance in c++, and they are also keyword virtual-related definitions.

First, let's talk about inheriting more. If Grandpa (the parent of the parent is temporarily named Grandpa), the parent inherits from Grandpa.If a grandchild inherits from more than one parent (which sounds a bit strange), then if you don't use a virtual base class, you instantiate multiple grandparents (the more bizarre it is), and the compiler will error and say it's ambiguous.If the parent inherits from a virtual base class, you can solve the problem that multiple parents will not instantiate multiple grandparents, that is, there is only one grandfather.

class Grandfather{  
public:  
    int flag;  
    Grandfather(){  
        flag = 1;  
    }  
};  
class Father1:public Grandfather{  
public:  
    Father1(){  
        flag = 2;  
    }  
};  
class Father2:public Grandfather{  
public:  
    Father2(){  
        flag = 3;  
    }  
};  
class Son:public Father1,public Father2{  
};  
int main(int argc, const char * argv[])  
{  
    Son *son = new Son();  
    cout<<son->flag<<endl;//Compile error here, flag access is ambiguous because both parent classes have flag variables, ambiguous  
    return 0;  
}  

If you do not use a virtual base class, multiple parent classes inherit from the same grandparent class, resulting in ambiguity. To avoid ambiguity, the code can be changed to (cure symptoms without cure):

cout<<son->Father1::flag<<endl;
cout<<son->Father2::flag<<endl;

If the parent inherits a virtual base class, it is different:

class Grandfather{  
public:  
    int flag;  
    Grandfather(){  
        flag = 1;  
        cout<<"Grandfather flag = "<<flag <<endl;  
    }  
};  
class Father1:virtual public Grandfather{  
public:  
    Father1(){  
        flag = 2;  
        cout<<"Father1 flag = "<<flag<<endl;  
    }  
};  
class Father2:virtual public Grandfather{  
public:  
    Father2(){  
        flag = 3;  
        cout<<"Father2 flag = "<<flag<<endl;  
    }  
};  
class Son:public Father1,public Father2{  
};  
int main(int argc, const char * argv[])  
{  
    Son *son = new Son();  
    cout<<son->flag<<endl;  
    return 0;  
}  

Result:

Grandfather flag = 1

Father1 flag = 2

Father2 flag = 3

3

Now it's ready to run, class Father2:virtual public Grandfather, which inherits the writing of virtual base classes. There is only one Grandpa object and only one Grandpa variable instantiated once. So why did 3 print out last?Looking at the order of the constructors, you can see that grandparents are now constructed, the first inherited parent is constructed, and the second inherited parent is finally inherited, so flag remains in the modified value of the second parent.

In general, virtual functions, pure virtual functions are for polymorphic services, and virtual base classes are for instantiating the existence of a base class only once

Posted by cockney on Wed, 20 Nov 2019 13:40:47 -0800