In-depth analysis of virtual functions and virtual inheritance in C++: advanced features for implementing polymorphism and inheritance relationships

virtual function

A virtual function is a special function used to implement polymorphism in C++. It is declared using the keyword "virtual", is defined in the base class, and can be overridden in derived classes. Virtual functions allow the corresponding function to be called at runtime based on the actual type of the object, not just the type of the pointer or reference. This allows in an inheritance relationship, when calling a virtual function through a base class pointer or reference, the function version to be executed can be dynamically determined based on the type of the actual object, achieving polymorphism.

virtual function definition

In C++, a virtual function can be defined by preceding the function declaration with the keyword virtual. For example:

class Base {
    
    
public:
    virtual void virtualFunction() {
    
    
        // 函数定义
    }
};

In this example, virtualFunction is declared virtual. Derived classes can override this virtual function to achieve polymorphism.

Virtual functions implement dynamic binding

Dynamic Binding, also known as runtime polymorphism, is achieved by using virtual functions in base and derived classes.

In C++, when a pointer or reference of a base class points to an object of a derived class, a specific implementation corresponding to the derived class can be implemented by calling a virtual function. This mechanism of determining which function to call based on the actual type of the object is dynamic binding.

The key to dynamic binding is to use the virtual keyword to declare member functions as virtual functions and provide corresponding implementations in base and derived classes.

#include<iostream>
#include <cstring>
using namespace std;
class cemployee
{
    
    
    public:
        int m_id;
        char name[10];
        cemployee()
        {
    
    
            memset(name,0,10);
        }
      virtual  void outputname()
        {
    
    
            cout<<"employee name:"<<name<<endl;
        }
};
class comployee:public cemployee
{
    
    
    public:
        char password[10];
        void outputname()
        {
    
    
            cout<<"opertor name:"<<name<<endl;
        }
};        
int main()
{
    
    
    cemployee* pworker = new comployee();
    strcpy(pworker->name,"MP");
    pworker->outputname();
    delete pworker;


    return 0;
}

Dynamic polymorphism satisfies the relationship:
1. There is an inheritance relationship
2. The subclass overrides the virtual function of the parent class< a i=3> Use of dynamic polymorphism: The pointer or reference of the parent class points to the subclass object Rewriting: The function return value type, function name, and parameter list are exactly the same, which is called rewriting

If there is no heap area data in the subclass, there is no need to write virtual destructor and pure virtual destructor.

1. Common characteristics between virtual destruction and pure virtual destruction:
Solving the problem of unclean release of subclass objects by parent class pointers
Both require specific Function implementation

2. Difference:
If it is pure virtual destruction, the class is an abstract class and cannot be instantiated
. Virtual destruction syntax: < /span> virtual ~class name()=0;< /span> Class name::~Class name(){} Pure virtual destructor syntax:
virtual ~class name(){}


Pure imaginary number
The content of the subclass will overwrite the parent class, so the function in the parent class is meaningless
As long as there is one pure virtual function in the class It is called an abstract class
virtual void func() = 0;
Abstract classes cannot instantiate objects (heap area, stack area)
Subclasses must also override the virtual functions in the parent class, otherwise the subclass will be an abstract class

The specific code is as follows

#include<iostream>
using namespace std;

class animal
{
    
    
public:
	void speak()
	{
    
    
		cout << "dongwuzaishouhua" << endl;
	}

	 void speak()
	{
    
    
		cout << "dongwuzaishouhua" << endl;
	}
	
class cat :public animal
{
    
    
public:
	void speak()
	{
    
    
		cout << "xiaomaozaishuohua" << endl;
	}
};
class dog :public animal
{
    
    
public:

	virtual void speak()
	{
    
    
		cout << "xioagouzaishuoihua" << endl;
	}
	//注释之后对象模型:

	class dog       size(1):
        +---
 0      | +--- (base class animal)
        | +---
        +---

};

void dospeak(animal& animal) //aniaml& aniaml= cat
{
    
    
	animal.speak();       //会打印出dongwuzaishouhua,因为aniaml& 
}
void test01()
{
    
    
	cat cat;
	dospeak(cat);
	dog dog;
	dospeak(dog);
}
/*
vfptr: 虚函数表指针
v- virtual
f- function
ptr- pointor
vftable:虚函数表
v- virtual
f- function
table- table
*/
![请添加图片描述](https://img-blog.csdnimg.cn/direct/0194baae48ad4111aa4acc0ce9f011df.png)

/* 有函数对象时模型:
class dog       size(4):
		+---
 0      | +--- (base class animal)
 0      | | {vfptr}
		| +---
		+---

dog::$vftable@:
		| &dog_meta
		|  0
 0      | &dog::speak  //覆盖 父类的指针或引用 指向子类对象发生多态

*/
class base
{
    
    
public:
	//纯虚数
	// 子类的内容会覆盖父类,所以父类中函数没有意义了
	//类中只要有一个纯虚函数就称为抽象类
	virtual void func() = 0;
	
	/*
        抽象类无法实例化对象(堆区,栈区)
		子类也必须要重写父类中的虚函数,否则子类也就是抽象类
	*/
	virtual ~base()
	{
    
    
		cout << "base的析构函数" << endl;
	}

};


class son :public base
{
    
    
public:
	virtual void func()
	{
    
    
		cout << "fff";
	}
	virtual ~son()
	{
    
    
		cout << "son的析构函数" << endl;
	}

};
void test00()
{
    
    
	//son s;不允许使用抽象类类型 "son" 的对象
	//base s;
	//new base;
	/*base* b = new son;
	b->func();*/


}
int main()
{
    
    

	//test01();
	test00();
	system("pause");
	return 0;
}

virtual inheritance

Please add image description

Virtual inheritance (Virtual Inheritance) is an inheritance method in C++ that is used to solve the diamond inheritance problem in multiple inheritance.

In multiple inheritance, a diamond inheritance problem occurs when a derived class inherits from two or more base classes that all inherit from the same base class. In this case, the derived class will contain multiple copies of the same base class, leading to ambiguity and wasted memory.

Virtual inheritance solves the diamond inheritance problem by using the virtual keyword to modify the base class and ensuring that only one shared base class sub-object is created when a derived class inherits the base class.

#include<iostream>
using namespace std;
class cnaimal
{
    
    
    public:
        cnaimal(){
    
    
        cout<<"animal was created"<<endl;
        }
        void move(){
    
    
            cout<<"animal could moving"<<endl;
        }
};
class cbird:public cnaimal
{
    
    
    public:
        cbird(){
    
    
            cout<<"bird was created"<<endl;
        }
        void fly(){
    
    
            cout<<"bird would flying"<<endl;
        }
};
class cfish:public cnaimal
{
    
    
    public:
        cfish(){
    
    
            cout<<"fish was created"<<endl;
        }
        void swim(){
    
    
            cout<<"fish would swim"<<endl;
        }
};
class cwaterbird: public cbird, public cfish
{
    
    
    public:
        cwaterbird(){
    
    
            cout<<"cwaterbird was created"<<endl;
        }
};
int main()
{
    
    
    cwaterbird waterbird;
    
    return 0;
}

operation result·:

[bsk@localhost polymorphic]$ g++ virtualinheritance.cpp 
[bsk@localhost polymorphic]$ ./a.out 
animal was created
bird was created
animal was created
fish was created
cwaterbird was created

We can see that when only one cwaterbird class is created, since it inherits from the cbird class and cfish class, their constructors will be called first, but they also inherit from the canimal class, so animal was created first. Then comes the bird's own structure, bird was created. After the bird is constructed, it is time to construct the fish. Just like the bird, first the animal was created, then its own structure, fish was created, and finally the waterbird was created.

#include<iostream>
using namespace std;
class cnaimal
{
    
    
    public:
        cnaimal(){
    
    
        cout<<"animal was created"<<endl;
        }
        void move(){
    
    
            cout<<"animal could moving"<<endl;
        }
};
class cbird:virtual public cnaimal
{
    
    
    public:
        cbird(){
    
    
            cout<<"bird was created"<<endl;
        }
        void fly(){
    
    
            cout<<"bird would flying"<<endl;
        }
};
class cfish:virtual public cnaimal
{
    
    
    public:
        cfish(){
    
    
            cout<<"fish was created"<<endl;
        }
        void swim(){
    
    
            cout<<"fish would swim"<<endl;
        }
};
class cwaterbird: public cbird, public cfish
{
    
    
    public:
        cwaterbird(){
    
    
            cout<<"cwaterbird was created"<<endl;
        }
};
int main()
{
    
    
    cwaterbird waterbird;
    
    return 0;
}

The result is as follows:

[bsk@localhost polymorphic]$ ./a.out 
animal was created
bird was created
fish was created
cwaterbird was created

It can be seen that when the class is virtual inheritance, we can find that there is only one constructor of the animal class.
Please add image description

abstract class

Abstract classes contain classes with pure virtual functions. An abstract class has at least one pure virtual function. An abstract class can only be used as a new subclass derived from the base class and cannot be instantiated in the program (objects of the abstract class cannot be declared), but it can point to pointers to the abstract class.

A pure virtual function is a virtual function declared in a base class that has no actual implementation. It is indicated by adding =0 after the function declaration.

Pure virtual functions play the role of defining interfaces in base classes, requiring derived classes to provide corresponding implementations. If a class contains pure virtual functions, then it becomes an abstract class and cannot be directly instantiated. It can only be used as a base class to derive other classes.

The syntax used by pure virtual functions is as follows:

class Base {
    
    
public:
    virtual void pureVirtualFunction() = 0;
};

In the above example, the pureVirtualFunction function in the Base class is declared as a pure virtual function. This function has no actual implementation and only exists as a definition of the interface.

Derived classes must provide implementations of pure virtual functions, otherwise they also become abstract classes. A derived class can choose to override a pure virtual function or continue to declare it as a pure virtual function, depending on whether the derived class needs to derive further.

A simple example:

#include <iostream>

class Base {
    
    
public:
    virtual void pureVirtualFunction() = 0;
};

class Derived : public Base {
    
    
public:
    void pureVirtualFunction() override {
    
    
        std::cout << "Derived class implementation." << std::endl;
    }
};

int main() {
    
    
    // Base base;  // 错误,无法实例化抽象类
    Derived derived;
    derived.pureVirtualFunction();  // 调用Derived类的实现

    Base* basePtr = &derived;
    basePtr->pureVirtualFunction();  // 通过基类指针调用Derived类的实现

    return 0;
}

In the above example, the pureVirtualFunction function in the Base class is declared as a pure virtual function. The Derived class inherits from the Base class and provides a specific implementation of pure virtual functions. The specific implementation of a pure virtual function can be called through an object of the Derived class or a base class pointer.

Pure virtual functions allow a set of interfaces to be defined in the base class and force derived classes to provide corresponding implementations. It is one of the important mechanisms for realizing abstract classes and polymorphism.
If a function is not a member function in an abstract class, it cannot be called with a base class pointer.

Guess you like

Origin blog.csdn.net/2202_75623950/article/details/134902325