First knowledge of virtual functions and polymorphism in C + + classes of C + +


Catalogue of series articles

 

Article catalog


preface


1, Virtual functions and virtual function tables

Virtual function creation method: add the keyword virtual before the class function

Example:

class A
{
public:
	virtual void ppd(){}//virtual function
	void ppee() {}//Ordinary function
protected:
};

Impact of virtual functions on classes:

When there are virtual functions in the class, the class memory of the class will change to 4 bytes; When there are only ordinary functions in the class, the size of the class is 1 byte; Note: no matter how many virtual functions there are, there are 4 bytes in the station; Because the existing class is a pointer to the virtual function table

  Because of this storage mode of virtual functions, virtual functions can be accessed through function pointers

Example:

class A
{
public:
	virtual void ppd1() { cout << "ppd1"<<endl; }
	virtual void ppd2() { cout << "ppd2" << endl; }
	virtual void ppd3() { cout << "ppd3" << endl; }
	
protected:
};

int main()
{
	A a;
	int** pp = (int**)&a;
	typedef void (*po)();
	po i = (po)pp[0][0];
	i();//Output ppd1 here
	i= (po)pp[0][1];
	i();//Output ppd2 here
	i=(po)pp[0][2];
	i();//Output ppd3 here
	
	return 0;
}

Although it can be accessed in this way, it is generally not supported to write in this way; It can be used to install 13, but it is not practical;


2, Virtual functions and polymorphisms

Polymorphism definition: different results caused by the same behavior (call)

Principle of necessity of polymorphism

  • A virtual function must exist in the parent class

  • Subclasses must adopt public inheritance

  • There must be a reference to the pointer (use)

Here are some examples:

class A
{
public:
	virtual void ppd1() { cout << "Appd1"<<endl; }
	virtual void ppd2() { cout << "Appd2" << endl; }
	virtual void ppd3() { cout << "Appd3" << endl; }
	
protected:
};
class B :public A
{public:
	void ppd1() { cout << "Bppd1" << endl; }
	 void ppd2() { cout << "Bppd2" << endl; }
void ppd3() { cout << "Bppd3" << endl; }
protected:};

int main()
{
	//Ordinary calls cannot see the difference
	B b;
	A a;
	b.ppd2();//The called is the ppd1 function in B
	a.ppd2();//The called is the ppd1 function in A
	//You must initialize the parent object with a child object to see the difference
	A* c = new B;
	c->ppd1();//Note that the function in B is called here

	return 0;
}

  It is this property of virtual function that creates polymorphism; I can create templates through this nature

For example:

class A
{
public:
	virtual void ppd1() { cout << "Appd1"<<endl; }
	virtual void ppd2() { cout << "Appd2" << endl; }
	virtual void ppd3() { cout << "Appd3" << endl; }
	
protected:
};
class B :public A
{public:
	void ppd1() { cout << "Bppd1" << endl; }
	 void ppd2() { cout << "Bppd2" << endl; }
void ppd3() { cout << "Bppd3" << endl; }
protected:};
class C :public A
{
public:
	void ppd1() { cout << "Newly added" << endl;}
protected:

};
void xiaog(A* i)//application program interface
{
	i->ppd1();
	i->ppd2();
	i->ppd3();
}
int main()
{
	xiaog(new C);
	xiaog(new B);

	return 0;
}

  This can facilitate our subsequent updates. If we do not use virtual functions, we cannot avoid modifying classes when changing functions. However, after using virtual functions, we can add new functions by adding code, such as adding a new class;

3, Pure virtual function and ADT

Pure virtual functions are also virtual functions, but pure virtual functions have no function body

virtual void prin()=0;

  ADT is also called abstract class;

Abstract class: a class with at least one pure virtual function is called an abstract class

  • Abstract classes cannot build objects

  • Abstract classes can build object pointers

Note: when an abstract class is inherited and not overridden, the subclass will also become an abstract class;

​
class A
{public:
virtual void aaa()=0;
protected:
};
class B:public A
{public:
protected:
};
class C:public B
{public:
protected:
};

​

  Class B and class C in the above code are abstract classes because they do not rewrite aaa functions;

After having abstract classes, you can better build template functions. Because abstract classes cannot create objects, they are more suitable for making template classes; After making the template class, you can give it to others to write the required functions according to the template class;

Template example:

class mom
{public:
	virtual void name() = 0;
	virtual void lian() = 0;
	virtual void snan() = 0;

protected:
};

4, Virtual destructor

When initializing a parent class with a subclass, if you need to call the destructor in the subclass, you need to use the virtual destructor;

Example:

class A
{
public:
	
	virtual void ppd1() { cout << "Appd1"<<endl; }
	virtual void ppd2() { cout << "Appd2" << endl; }
	virtual void ppd3() { cout << "Appd3" << endl; }
	virtual ~A()//If the virtual destructor is not used here, the destructor in the subclass will not be called;
	{
		cout << "AA" << endl;
	}
protected:
};

class B :public A
{public:
	void ppd1() { cout << "Bppd1" << endl; }
	 void ppd2() { cout << "Bppd2" << endl; }
void ppd3() { cout << "Bppd3" << endl; }
~B()
{
	cout << "BB" << endl;
}
protected:};

int main()
{
A *a=new B;
delete a;//Note that the destructors of both parent and child classes will be called here
return 0;

}

 

5, C + + type conversion

c + + provides us with a type conversion method that has become safe in rumors;

  • const_cast       // It can be used for type conversion of const attribute;

usage method

const int A;
int B=const_cast<int&>(A); //< > must be pointer type or reference type;
  • static_cast    // You can convert the pointer of the parent class to the pointer of the child class// Other functions can be done by implicit conversion, and it can also be done;

int main()
{
    //Do not use static_cast
	int *u=new int(10);
	void *e = u;
    //Using static_cast
	int* ui = new int(20);
	void* y = static_cast<void*>(ui);

	//A. B is two classes and a is the parent class of B;
	A* a=new A;
	B* b =static_cast<B*>(a);//The only thing I think is useful
	return 0;
}
  • dynamic_cast   // Basic and static_cast is the same, except that when the pointer of the parent class is converted to a subclass, an error will be reported when calling a function in the subclass but not in the parent class; static_cas will not continue to call;

  • reinterpret_cast     // Used to convert data types

    int i = 0x00636261;
	char* ii = reinterpret_cast<char*>(&i);


summary

Thank you for reading it. I also hope you can give me a big praise. Thank you

Keywords: C C++

Added by megaalf on Tue, 07 Dec 2021 12:38:12 +0200