C++多态

多态表现出来的现象就是:父类的指针指向谁的对象就调用谁;

一。区分 函数重载,重写(同名隐藏),重定义(覆盖) ,协变;

函数重载

同一作用域
相同函数名,不同参数(类型,数量,顺序)
返回值不限

重写(同名隐藏)
不同作用域
函数名相同

重定义

不同作用域
函数名,参数列表,返回值统统相同
基类函数必须加virtual关键字

构成多态必须要满足以下两点要求;

1,重定义

2,父类的指针指向子类的对象


二。下面给出实例

1,既构不成多态,父类指针也没有指向子类;

class Base
{
public:
	void f1()
	{
		cout << " f1():base()" << endl;
	}

	/*virtual  void f2()
	{
		cout << " f2():base()" << endl;
	}*/
protected:
	int _b;
};

class Drive :public Base
{
public:
	 virtual void f1()
	{
		cout << " f1():drive()" << endl;
	}

	/*void f2()
	{
		cout << " f2():drive()" << endl;
	}*/
protected:
	int _d;
};

int main()
{
	Base b;
	Drive d;
	b.f1();
	d.f1();

	//Base* p = &b;
	p=&d;
	//p->f();
	return 0;
}






2,子类函数前加virual关键字,父类不加,父类指针指向子类;(构不成多态)

class Base
{
public:
	void f1()
	{
		cout << " f1():base()" << endl;
	}

	/*virtual  void f2()
	{
		cout << " f2():base()" << endl;
	}*/
protected:
	int _b;
};

class Drive :public Base
{
public:
	 virtual void f1()
	{
		cout << " f1():drive()" << endl;
	}

	/*void f2()
	{
		cout << " f2():drive()" << endl;
	}*/
protected:
	int _d;
};

int main()
{
	
	/*b.f1();
	d.f1();*/

	Base b;
	Drive d;
	Base* p = &b;
	p->f1();
	p=&d;
	p->f1();
	return 0;
}


结果和上面一模一样




3,延续第二种情况,将子类的virtual关键字加到父类;(构成多态)






总结;先看有没有构成多态,必须满足这两点,1,构成重写,2,父类指针指向子类 ,
由例2和例3可以看出奇遇不变只要将子类的关键字加到父类之前就构成了多态,如果其他条件都满足,只想加一个virtual构成多态,必须加到父类父类上;
如果不能构成多态,调用子类还是父类的函数由所调函数的对象或者是指针决定;父类对象或指针调用的就是父类成员函数,子类对象或指针调用的就是子类的成员函数,
如果构成多态,则父类的指针指向谁就调用谁的成员函数;


三。揭秘多态的底层面纱

其实

不通过内存窗口而是在屏幕上打印出程序的底层,

#include<iostream>
using namespace std;

class Base1
{
public:
	 virtual void f1()
	{
		cout << " base1:f1()" << endl;
	}
	virtual  void f2()
	{
		cout <<" base1:f2()"  << endl;
	}
	 
protected:
	int _b;
};

class Base2
{
public:
	  virtual void y1()
	{
		cout << "base2: y1()" << endl;
	}
	virtual void y2()
	{
		cout << " base2:y2()"  << endl;
	}
protected:
	int _b2;
};

class Drive :public Base1, public Base2
{
public:
	virtual void f1()
	{
		cout << " drive:f1()" << endl;
	}
	void z1()
	{
		cout << " drive:z1()" << endl;
	}
	virtual void z2()
	{
		cout << " drive:z2()" << endl;
	}
protected:
	int _d;
};


typedef void(*v_FUNC)();
void  PrintVTable(Base1 &b1)
{
	
	v_FUNC vTable = (v_FUNC)*(int*)(*(int*)(&b1));
	int i = 0;
	while (vTable)
	{
		i++;
		vTable();
		vTable = (v_FUNC)(*((int *)(*(int*)(&b1)) + i));
	}
	cout << endl;
}

typedef void(*v_FUNC)();
void  PrintVTable(Base2 &b2)
{

	v_FUNC vTable = (v_FUNC)*(int*)(*(int*)(&b2));
	int i = 0;
	while (vTable)
	{
		i++;
		vTable();
		vTable = (v_FUNC)(*((int *)(*(int*)(&b2)) + i));
	}
	cout << endl;
}
typedef void(*v_FUNC)();
void  PrintVTable(Drive &d)
{

	v_FUNC vTable = (v_FUNC)*(int*)(*(int*)(&d));
	int i = 0;
	while (vTable)
	{
		i++;
		vTable();
		//printf("%p\n", &vTable);//为什莫地址每次是随机的一致;
		vTable = (v_FUNC)(*((int *)(*(int*)(&d)) + i));
	}
	
}
int main()
{
	
	/*b.f1();
	d.f1();*/

	Base1 b1;
	Base2 b2;
	Drive d;
	/*Base* p = &b;
	p->f1();
	p=&d;
	p->f1();*/
	PrintVTable(b1);
	PrintVTable(b2);
	PrintVTable(d);
  
	return 0;
}




运行结果;


多继承中,子类新的成员函数保存在先被继承的父类的虚函数表中;




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值