C++ learning summary (20) - virtual functions, overloading characteristics of virtual functions, abstract classes of pure virtual functions, virtual function tables, heterogeneous linked lists

Virtual function: A virtual function is equivalent to a function pointer, occupying four bytes (for 32 bits), and a virtual function in a class occupies four bytes, and its member functions do not occupy the memory of the class.

The base class defines a virtual function, and the function of the same name in the subclass is called first, overwriting the virtual function. Base class pointers access different derived objects and call different methods.

Note: 1. The virtual function must be a member function of the class

         2. A friend function cannot be declared as a virtual function, but a virtual function can be a friend of another class.

         3. Destructors can be virtual functions, but constructors cannot be virtual functions.

#include<iostream>
using namespace std;
class base1
{
public:
	virtual int run() = 0;
	virtual double go() = 0;
};

class base2
{
public:
	virtual void run()
	{

	}
	virtual void go()
	{

	}
};

void main()
{
	cout << sizeof(base1)<<endl;
	cout << sizeof(base2) << endl;


	cin.get();

}

When the parent class object pointer points to the derived class object, the subclass destructor will be automatically called when destructing,

#include<iostream>
class base
{
public:
	 virtual void name() //The virtual function occupies a four-byte address
	{
		std::cout << "base" << std::endl;
		std::cout << "x=" << x << std::endl;
	}
	int x;
	base(int a) :x(a)
	{

	}
};
class zi :
	public base
{
	public:
		void name()
		{
			std::cout << "zi" << std::endl;
			std::cout << "x=" << x << "y=" << y<< std::endl;
		}

		int y;
		zi(int a,int b) :base(a),y(b)
		{

		}
};
class sun :
	public day
{
public:
	void name()
	{
		std::cout << "sun" << std::endl;
		std::cout << "x=" << x << "y=" << y << "z=" << z << std::endl;
	}
	int z;
	sun(int a,int b,int c) :zi(a,b),z(c)
	{

	}
};
// Migration of parent class pointer
void main()
{
	base p1(1);
	day p2 (2.3);
	sun p3(4,5,6);
	base *p;

	p = &p1; //Access parent class member data
	p->name(); //The base class is the function of the virtual function that first accesses the derived class

	p = &p2; //Access the data of parent class members inherited by subclass members
	p->name();

	p = &p3;//Access the data of parent class members inherited by grandchild class members
	p->name();

	std::cout << sizeof(base) << std::endl;

	std::cin.get();



}
void main1()
{
	base *pb = new base(1);
	pb->name();

	day * pz = new day (2,3);
	pz->name();

	sun *ps = new sun(4,5,6);
	ps->name();
 
	zi *p =static_cast<zi *>(pb) ;
	p->name();


	std::cin.get();
}

When the destructor is virtual, the destructors of the derived and base classes are automatically called.

#include<iostream>

class my
{
public:
	//virtual constructor cannot be virtual
	my()
	{
		std::cout << "my creat" << std::endl;
	}
	virtual
		~my() //When the destructor is a virtual function, the derived class will automatically call the destructor of the derived class when destructing, destructing the derived class and the base class
	{
		std::cout << "my delete" << std::endl;
	}
};

class myzi :public my
{
public:
	myzi()
	{
		std::cout << "myzi creat" << std::endl;
	}
	~myzi()
	{
		std::cout << "myzi delete" << std::endl;
	}

};
void run()
{
	/*my *p = new my;
	delete p;*/

	my *p1 = new myzi;
	delete p1;
}
void main3()
{
	run();
	std::cout << "hello world!" << std::endl;

	std::cin.get();
}

Virtual function overloading features:

1. Any function properties in the derived class should be the same as in the base class.

2. The return type should be the same, otherwise it is considered an error overload.

3. The prototype is different, only the function name is the same, and the virtual function feature is lost.

#include<iostream>

class A
{
public:
	virtual int run()
	{
		return 1;
	}
	virtual int go()
	{
		return 0;
	}

};

class B :public A
{
public:
     virtual int run()
	{
		return 2;
	}
	 //void go()
	 //{

	// }

};

void main4()
{
	B c;
	std::cout<<c.A::run()<<std::endl;

	std::cin.get();
}

Pure virtual function abstract class.

1. Pure virtual function, the virtual function is described in the base class, but not defined in the base class, requiring any derived class to define its own version.

2. Pure functions are used as a public interface for derived classes.

3. Base class abstract class with pure virtual functions. There is no way for abstract classes to be instantiated, but to be instantiated through derivation.

4. Abstract classes cannot be used for function parameters and return value types, but abstract class pointers can.

5. The virtual function table is located in the code area of ​​the compiler, the virtual function pointer points to the virtual function table, and one or more virtual functions occupy four bytes.

#include<iostream>

// abstract class
class A
{
public:
	int a;
	virtual void show() = 0;
	virtual void go() = 0;//Pure virtual function

};

class B :public A
{
public:
	int num;
	void show()
	{
		std::cout << "B show()" << std::endl;
	}
	void go()
	{
		std::cout << "B go()" << std::endl;
	}
};

A *test()
{
	A *p(nullptr);
	return p;
}
void main5()
{
	B c;
	//A aa;//Abstract classes cannot instantiate objects, but can instantiate pointers;
	A *p;
	c.go();
	c.show();

	std::cin.get();
}

Heterogeneous linked list: Use the base class to store the derived class pointer, and use the base class pointer to receive the address of the derived class. Use the base class pointer to generate a dynamic linked list connecting different derived class objects, each node pointer points to different derived class objects in the class hierarchy. Linked lists with different node types.

#include<iostream>
#include<Windows.h>
#include<stdlib.h>
using namespace std;
class base
{
public:
	virtual void show() = 0;
};

class linknode
{
public:
	base *p; //data field
	linknode *pnext; //Pointer field
};

class A :public base
{  
public:
	void show()
	{
		cout << "class A\n";
	}

};

class B :public base
{
public:
	void show()
	{
		cout << "class B\n";
	}
};

class C :public base
{
public:
	void show()
	{
		cout << "class C\n";
	}
};
class D:public base
{
public:
	void show()
	{
		cout << "class D\n";
	}
};
void showall(linknode *phead)
{
	while (phead != NULL)
	{
		phead->p->show();
		phead = phead-> pnext;
	}
}
void add(linknode *phead, base *p)
{
	linknode * ptemp = phead;
	if (ptemp == NULL)
	{
		ptemp->p = p;
		ptemp->pnext = NULL;
	}
	else
	{
		while (ptemp->pnext != NULL)
		{
			ptemp = ptemp->pnext;
		}
		linknode *padd = new linknode; //Create a new node and insert it at the end of the linked list
		padd->p = p;
		padd->pnext = NULL;

		ptemp->pnext = padd; //Let the previous node point to the new node
	}
	
}
void main()
{
	linknode * phead;
	linknode node1, node2, node3;
	A a1,a2,a3;
	B b1,b2,b3;
	C c1,c2,c3;
	D d1;
	phead = &node1; //pointer to
	node1.pnext = &node2;
	node2.pnext = &node3;
	node3.pnext = NULL;

	node1.p = &a1; //Data stored by the node
	node2.p = &b1;
	node3.p = &c1;



	showall (phead);
	add(phead,&d1);
	showall (phead);

	cin.get();
}


Guess you like

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