虚函数&多态

  • 虚函数在类的成员函数前加virtual关键,这时成员函数就是虚函数。这里需要注意的是必须是类的成员函数。
  • 虚函数表通过一块连续的内存来存储虚函数地址。在对象的模型里存着。如下所示:

class Base
{
public:
	
	virtual void Fun1()
	{
		cout << "Base::Fun1()" << endl;
	}

	virtual void Fun2()
	{
		cout << "Base::Fun2()" << endl;
	}

public:
	int _Base;
};

class Derive:public Base
{
public:
	virtual void Fun1()
	{
		cout << "Derive::Fun()" << endl;
	}

	virtual void Fun3()
	{
		cout << "Derive::Fun3()" << endl;
	}

	virtual void Fun4()
	{
		cout << "Derive::Fun4()" << endl;
	}
public:
	int _Derive;

};
上述的图示(单继承):


菱形虚拟继承:(多继承)

下面通过一段简单的菱形继承的代码来分析:

//菱形虚拟继承博客演示

class A
{
public:
	virtual void f1()
	{
		cout << "A::f1()" << endl;
	}

	virtual void f2()
	{
		cout << "A::f2()" << endl;
	}

	int _a;
};

class B :virtual public A
{
public:
	virtual void f1()
	{
		cout << "B::f1()" << endl;
	}
	
	virtual void f3()
	{
		cout << "B::f3()" << endl;
	}

	int _b;
};

class C :virtual public A
{
public:
	virtual void f1()
	{
		cout << "C::f1()" << endl;
	}

	virtual void f4()
	{
		cout << "C::f4()" << endl;
	}

	int _c;
};

class D :public B, public C
{
public:

	virtual void f1()
	{
		cout << "D::f1()" << endl;
	}

	virtual void f5()
	{
		cout << "D::f5()" << endl;
	}

	int _d;
};

typedef void(*VfTables)() ;               //函数指针
void printVfptr(int **VfTable)
{
	printf("虚表的地址:%p \n",VfTable);
	for (size_t i = 0; VfTable[i] != 0; ++i)
	{
		printf("VfTable[%d] :%p -> ",i,VfTable[i]);
		VfTables func = (VfTables)VfTable[i];
		func();
	}
}

int main()
{

	D d;
	d._a = 1;
	d._b = 2;
	d._c = 3;
	d._d = 4;

	cout << "====================================" << endl;
	printVfptr(((int**)(*(int**)&d)));
	cout << "====================================" << endl;
	printVfptr((int**)(*((int**)((char*)&d + sizeof(B)-sizeof(A)))));
	cout << "====================================" << endl;
	printVfptr((int**)(*(int**)((char*)&d + sizeof(D)-sizeof(A))));
	cout << "====================================" << endl;

	return 0;
}

图示分析:



  • 多态即多种形态


触发多态的条件:1.父类的指针或引用调用虚函数

                            2.虚函数的重写(覆盖)

下面代码实现多态

class A
{
public:
	virtual void Fun1()
	{
		cout << "A::Fun1" << endl;
	}

	void GetFun()
	{
		Fun1();
	}
};

class B :public A
{
public:
	virtual void Fun1()
	{
		cout << "B::Fun1" << endl;
	}
};

int main()
{
	A a;
	B b;
	A* pa = &a;
	pa->GetFun();

	pa = &b;
	pa->GetFun();
}

这里就可以看出来的,pa是一个A*的类型,但是通过同一类型的指针,调了两个不同的函数,一个是父类的Fun1,一个是子类的Fun1。


重写,重载,隐藏的区别:







猜你喜欢

转载自blog.csdn.net/skinwhite/article/details/78445950