多态与多态对象模型

 在介绍多态之前,我们应该知道什么是虚函数?什么是虚函数重写?
     虚函数:
      类的 成员函数 前面加virtual关键字,则这个成员函数称为虚函数。
    注:除静态成员函数

   虚函数重写:

当在子类的定义了一个与父类 完全相同的 虚函数时,则称子类的这个函数 重写(也称覆盖)了父类的这个虚函数。

多态

    定义:

             当使用 基类的指针或引用调用重写的虚函数时,当指向父类调用的就是父类的虚函数,当指向子类调用的就是子类的虚函数。
    条件:
          1.虚函数重写  2.父类的指针和引用
eg:

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

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

public:
	int a ;
};

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

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

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

public:
	int b ;
};

    这是一种运行期多态,即父类指针唯有在程序运行时才能知道所指的真正类型是什么。这种运行期决议,是通过虚函数表来实现的。
多态对象模型

     使用指针访问虚表
   eg:
class Base
{
public :
	virtual void func1()
	{
		cout<<"Base::func1" <<endl;
	}

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

public:
	int a ;
};

typedef void(*V_FUNC)();

void PrintVTable(int** vtable)
{
	cout<<"===================================="<<endl;

	printf("虚函数表:%p\n", vtable);
	for (size_t i = 0; vtable[i] != 0; ++i)
	{
		printf("vfunc[%d]:%p->", i, vtable[i]);
		V_FUNC f = (V_FUNC)vtable[i];
		f();
	}
	cout<<"===================================="<<endl;
}

void Test()
{
	Base b;
	PrintVTable((int**)(*((int**)&b)));
}

分析:

单继承对象模型

写一个类继承Base
eg:
class Derive :public Base
{
public :
	virtual void func1()
	{
		cout<<"Derive::func1" <<endl;
	}

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

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

public:
	int _b ;
};

分析:
    在C++对象模型中,对于一般继承(这个一般是相对于虚拟继承而言),若子类重写(overwrite)了父类的虚函数,则子类虚函数将覆盖虚表中对应的父类虚函数(注意子类与父类拥有各自的一个虚函数表);若子类并无overwrite父类虚函数,而是声明了自己新的虚函数,则该虚函数地址将扩充到虚函数表最后(在vs中无法通过监视看到扩充的结果,不过我们通过取地址的方法可以做到,子类新的虚函数确实在父类子物体的虚函数表末端)。
  多继承对象模型(非菱形继承)
eg:
class Base1
{
public :
	virtual void func1()
	{
		cout<<"Base1::func1" <<endl;
	}

	virtual void func2()
	{
		cout<<"Base1::func2" <<endl;
	}

private :
	int b1 ;
};

class Base2
{
public :
	virtual void func1()
	{
		cout<<"Base2::func1" <<endl;
	}

	virtual void func2()
	{
		cout<<"Base2::func2" <<endl;
	}

private :
	int b2 ;
};


class Derive : public Base1, public Base2
{
public :
	virtual void func1()
	{
		cout<<"Derive::func1" <<endl;
	}

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

private :
	int d1 ;
};


typedef void(*V_FUNC)();

void PrintVTable(int** vtable)
{
	cout<<"===================================="<<endl;

	printf("虚函数表:%p\n", vtable);
	for (size_t i = 0; vtable[i] != 0; ++i)
	{
		printf("vfunc[%d]:%p->", i, vtable[i]);
		V_FUNC f = (V_FUNC)vtable[i];
		f();
	}
	cout<<"===================================="<<endl;
}

void Test()
{
	Derive d;
	PrintVTable((int**)(*((int**)&d)));
	PrintVTable((int**)(*(int**)((char*)&d+sizeof(Base1))));

}

分析:

    单继承中(一般继承),子类会扩展父类的虚函数表。在多继承中,子类的虚函数被放在声明的第一个基类的虚函数表中。

猜你喜欢

转载自blog.csdn.net/smile_zhangw/article/details/79341245