Virtual functions and polymorphism

Knowledge reserve:

Reintroduce slicing behavior:

1. Subclass object is assigned to parent class object

2. The pointer of the parent type points to the subclass object

3. The reference of the parent type refers to the object of the subclass



Virtual function: The virtual keyword is added in front of the member function of the class, then this member function is called a virtual function

Virtual function rewriting: When a virtual function that is exactly the same as the parent class is defined in the subclass, the function of the subclass is said to override (also known as overriding) the virtual function of the parent class.

The conditions that need to be met to constitute polymorphism:

1. The formal parameter of the function is a pointer or reference to the parent class

2. The called Func must be a rewrite of the virtual function

The invocation of the function that constitutes polymorphism is only related to the object that calls the function function, (the parent class object or the subclass object)

Regular function calls are only related to the type, (parent or child)

class Person
{
public:
	virtual void BuyTickets()
	{
		cout << " 全价" << endl;
	}
protected:
	string _name; // name
};
class Student : public Person
{
public:
	virtual void BuyTickets()
	{
		cout << "半价" << endl;
	}
protected:
	int _num; //student number
};
//void Fun(Peron p) //Does not constitute polymorphism, it is related to the type, and the functions of the base class are called here
//void Fun(Person* p) //Constitute polymorphism
void Fun(Person& p) //Constitute polymorphism
	// regular calls that aren't polymorphic enough -- type-dependent
	// constitute polymorphism -- related to objects
	// Constitute polymorphic behavior
	// 1. Parent class pointers and references
	// 2. The func called must be a rewrite of the virtual function
{
	p.BuyTickets();
}
void Test()
{
	Person p;
	Student s;
	Fun(p);
	Fun(s);
}

Summarize:

1. The derived class rewrites the virtual function of the base class to achieve polymorphism, requiring the function name, parameter list, and return value to be exactly the same. (except for covariation)

2. A virtual function is defined in the base class, and the function always maintains the characteristics of a virtual function in the derived class

3. Only non-static member functions of a class can be defined as virtual functions , and static member functions cannot be defined as virtual functions

4. If a virtual function is defined outside the class, virtual can only be added when the function is declared, and virtual cannot be added when the function is defined outside the class.

5. The constructor cannot be a virtual function . Although operator= can be defined as a virtual function, it is best not to define operator= as a virtual function, because it is easy to cause confusion when it is easy to use.

6. Do not call virtual functions in constructors and destructors. In constructors and destructors, objects are incomplete and undefined behavior may occur.

7. It is best to declare the destructor of the base class as a virtual function . (Why? The destructor is special, because the destructor of the derived class has a different name than the destructor of the base class, but it constitutes coverage, because the compiler has done special processing)

8. The virtual table is shared by all class object instances

class A //It is best to declare the destructor of the base class as a virtual function
{
public :
	virtual ~A()
	{
		cout << "~A()" << endl;
	}
};

class B :public A
{
public:
	~B()
	{
		cout <<"~B()" << endl;
	}
};

intmain()
{
	B b;
	A& ra = b;
	A* p = new B;		
	delete p; // p->destructor() + free(p)---- only destructs A but not B, if there is an operation to release memory in ~B(), it will cause a memory leak
                 //Solution: define the destructor of the parent class as a virtual function
                //Slice occurs first here, the pointer p of type A points to the B object,
	       //When the destructor of the parent class is written as a virtual function, when it is actually called, the polymorphism has nothing to do with the type of the type pointer, and the destructor of B is directly adjusted
	system("pause");
	return 0;
}
Pure virtual function: Write =0 after the formal parameter of the member function, then the member function is a pure virtual function. Classes that contain pure virtual functions are called abstract classes (also called interface classes) , and abstract classes cannot instantiate objects. After the pure virtual function is redefined in the derived class, the derived class can instantiate the object.

class Person
{
public:
	virtual void Display() = 0; //Pure virtual function
protected:
	string _name;
};

class Teacher : public Person
{
	virtual void Display()
	{
		cout << "Teacher" << endl;
	}
protected:
	string _name;
};

class Student : public Person
{
	virtual void Display()
	{
		cout << "Student" << endl;
	}
protected:
	string _name;
};

intmain()
{
	//Person p; //Error - abstract class cannot create object
	Person* p = new Teacher;
	p->Display();

	p = new Student;
	p->Display();

	return 0;
}






Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324886186&siteId=291194637