虚函数用法总结

#include<iostream>
using namespace std;
class Class {};
class Base :public Class
{
public:
	Base() = default;
	Base(const Base&a) :ival(a.ival), dval(a.dval)
	{
		cout << "---Base----" << endl;
	}
	Base(int a, int b) :ival(a), dval(b)
	{
		cout << "---Base-a----" << endl;
		printf("a11= %d,b11= %d\n", a, b);
	}
	// virtual void print(){
	// 	printf("%d---1---%d\n",dval,ival );
	// }
	void print() {
		printf("%d---1---%d\n", dval, ival);
	}
	int dval;
protected:
	int ival;
};
class D1 :   public Base//因为是虚基,因此可以有不同形参的同名函数print;若不是虚基,则不可以有不同形参的同名函数
{
public:
	D1() = default;
	D1(const D1&a) :Base(a.ival, a.dval)
	{
		cout << "---D1----" << endl;
	}
	D1(int a, int b) :Base(a, b)
	{
		cout << "---D1-a----" << endl;
	}
	// void print(int a)
	// {
	// 	printf("---2---%d----2---\n", a);
	// }
};
int main()
{
	D1*pi;
	int i = 4, j = 7;
	pi = new D1(i, j);
	//对于Mi而言,使用Final中的Mi类进行初始化
	Base*pmi = new Base(*pi);//指向虚基类,但并未初始化
	pi->print(111);
}

#include<iostream>
using namespace std;
class Class {};
class Base :public Class
{
public:
	Base() = default;
	Base(const Base&a) :ival(a.ival), dval(a.dval)
	{
		cout << "---Base----" << endl;
	}
	Base(int a, int b) :ival(a), dval(b)
	{
		cout << "---Base-a----" << endl;
		printf("a11= %d,b11= %d\n", a, b);
	}
	// virtual void print(){
	// 	printf("%d---1---%d\n",dval,ival );
	// }
	void print() {
		printf("%d---1---%d\n", dval, ival);
	}
	int dval;
protected:
	int ival;
};
class D1 :  public Base//因为是虚基,因此可以有不同形参的同名函数print;若不是虚基,则不可以有不同形参的同名函数
{
public:
	D1() = default;
	D1(const D1&a) :Base(a.ival, a.dval)
	{
		cout << "---D1----" << endl;
	}
	D1(int a, int b) :Base(a, b)
	{
		cout << "---D1-a----" << endl;
	}
	void print()
	{
		printf("---2---%d----2---\n", ival);
	}
};
class D2 :virtual public Base
{
public:
	D2() = default;
	D2(const D2&a) :Base(a.ival, a.dval)
	{
		cout << "---D2----" << endl;
	}
	D2(int a, int b) :Base(a, b)
	{
		cout << "---D2-a----" << endl;
	}
};
class Mi :public D1/*,public D2*/
{
public:
	Mi() = default;
	Mi(const Mi&a) :Base(a.ival, a.dval)/*,D2(a.ival,a.dval)*/, D1(a.ival, a.dval)
	{
		cout << "---Mi----" << endl;
	}
	Mi(int a, int b) :Base(a, b), D1(a, b)/*,D2(a,b)*/
	{
		cout << "---Mi-a----" << endl;
		printf("a= %d,b= %d\n", a, b);
	}
};
class Final : public Mi, public Class
{
public:
	Final() = default;
	Final(const Final&a) :Base(a.ival, a.dval), Mi(a.ival, a.dval)
		// Final(const Final&a):Base(a.ival,a.dval),Mi(1,2)
	{
		cout << "---Final----" << endl;
	}
	// Final(int a,int b):Base(a,b),Mi(a,b)
	Final(int a, int b) :Base(a, b), Mi(1, 2)//首先Base被Base初始化了,然后Mi中的Base基类初始化就不再调用了
	{
		cout << "---Final-a----" << endl;
	}
};
int main()
{
	Final*pi;
	int i = 4, j = 7;
	pi = new Final(i, j);
	//对于Mi而言,使用Final中的Mi类进行初始化
	Mi*pmi = new Mi(*pi);//指向虚基类,但并未初始化
	pmi->print();
}

两段代码,可以调着进行理解使用

1.     只有一个基被标记为虚基,才能允许被间接访问

2.     当一个基,用派生类来构造它自己时,最后执行的函数,是基中的函数非派生类中的函数;同时,它也只能调用自己的函数,不能调用派生类中的函数

3.     派生类可以继承基类中的函数(即使没有在派生类中写出来);当写出来时,则派生类执行自己类内部的成员函数,不执行基类中的成员函数(非虚函数),但成员函数之间要求同名同形参

4.     当基类中的某个成员函数是虚函数时,则后面派生类中的同名成员函数可以有不同的形参

5.     总结:

a)      虚基,可以间接调用

b)      虚函数,派生类的同名函数可以有不同形参(当然也可以不写出来默认使用基类中的)


猜你喜欢

转载自blog.csdn.net/hgtjcxy/article/details/80501043
今日推荐