c++ 自学笔记:多态

c++ 自学笔记:多态

1.什么是多态

C++面向对象三大特征:封装、继承、多态

多态分两类:

  • 静态多态:包括 函数重载、运算符重载,复用函数名
  • 动态多态:包括 派生类、虚函数实现运行时多态

静态多态与动态多态区别:

  • 静态多态的函数地址早绑定——编译阶段确定函数地址
  • 动态多态的函数地址晚绑定——运行阶段确定函数地址

动态多态满足条件:

  • 有继承关系
  • 子类重写父类的虚函数(重写:函数返回值类型、函数名、参数列表完全相同),重写时virtual关键字可写可不写

动态多态使用情景:父类指针或引用指向子类对象

多态案例:

class Shizuma
{
public:
	virtual void eat()   //virtual关键字
	{
		cout << "始祖马吃草"<<endl;
	}
};
class Ma : public Shizuma
{
public:
	void eat()//重写父类虚函数时virtual关键字可写可不写
	{
		cout << "马吃草" << endl;
	}
};
class Lv : public Shizuma
{
public:
	void eat()
	{
		cout << "驴吃草" << endl;
	}
};

void myVirtualTest()//调用函数
{
	Shizuma *sz;
	Ma ma;
	Lv lv;
	sz=&lv;//父类指针指向子类对象
	(*sz).eat();//父类成员函数不加virtual输出“始祖马吃草”,加virtual后输出“驴吃草”
    sz=&ma;
    (*lv).eat();
}

2.动态多态的原理

实验:

/*===========TEST-1==============*/
class Shizuma
{
public:
	 void eat()   //不加virtual关键字
	{
		cout << "始祖马吃草"<<endl;
	}
};
void szofClass()
{
    cout<<sizeof(Shizuma);//输出:1,即此处的Shizuma类是个空类
}
/*===========TEST-2==============*/
class Shizuma
{
public:
	 virtual void eat()   //加了virtual关键字
	{
		cout << "始祖马吃草"<<endl;
	}
};
void szofClass()
{
    cout<<sizeof(Shizuma);//输出:4 ,为什么是4呢? 立即推:指针!
}
//注:任何类型的指针都只占4字节

思考:

上述指针是什么类型?指向何方?有何意图?

该指针为:vfptr—— virtual function pointer ——虚函数(表)指针

该指针指向:vftable—— virtual function table —— 虚函数表

虚函数表的作用:记录虚函数的函数入口地址

在前述多态案例中,考虑到:马类继承了始祖马类,那么,始祖马类(父类)的vfptr也给了马类(子类)一份,而且,作为子类的马类还重写了父类的虚函数virtual void eat(),这时,子类中的虚函数表内部会替换成子类的虚函数地址,在本案例中也即:马类重写的虚函数地址覆盖了继承自始祖马类的虚函数地址(始祖马类自己的vfptr指向的虚函数表没变)。当父类的指针或者引用指向子类对象时,父类接受的谁的对象,就利用虚函数(表)指针在谁的虚函数表中找对应的函数。
验证:
父类(Shizuma):
在这里插入图片描述
子类没有重写虚函数时:vfptr指向的虚函数表内容为&Shizuma::eat
在这里插入图片描述
子类重写父类虚函数后:vfptr指向的虚函数表内容为&Ma::eat
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值