浅析C++多态性

C++多态性 可以简单概括为“一个借口,多种方法”,程序在运行时才决定调用那个函数,这也是C++面对对象编程的核心。

C++多态性是通过虚函数来实现的,虚函数允许子类重新定义成员函数,而子类重新定义 父类的方式叫 覆盖也称重写
(提醒下:重写有两种:重写成员函数(这叫隐藏),重写虚函数,只有重写虚函数才能算真正体现C++多态性)。

参考:

多态与非多态的实质区别就是函数地址是早绑定还是晚绑定。如果函数的调用,在编译器编译期间就可以确定函数的调用地址,并生产代码,是静态的,就是说地址是早绑定的。而如果函数调用的地址不能在编译器期间确定,需要在运行时才确定,这就属于晚绑定。
参考:

C++有三大特性:封装,继承,多态
封装实现了代码模块化;继承可以扩展已存在的代码   ------->   他们都是为了实现代码的重用

多态的目的是为了借口重用,也即是,不论传递来的究竟是哪个类对象,函数都能通过同一个接口调用适应各自对象的实现方法。


最常用的方法:声明基类的指针,利用该指针 指向一个子类对象,调用相应的虚函数,可以根据指向的子类的不同而实现不同的方法。如果没有使用虚函数的话,即没有利用C++多态性,则利用基类指针调用相应的函数的时候,将总被限制在基类函数本身,而无法调用到子类中被重写过的函数。因为没有多态性,函数调用的地址将是一定的,而固定的地址将始终调用到同一个函数,这就无法实现一个接口,多种方法的目的了。

举例;
#include<iostream>
using namespace std;

class A   //基类
{
public:
	void foo()
	{
		cout << 1 << endl;
	}
	virtual void fun()  //虚函数
	{
		cout << 2 << endl;
	}
};
class B : public A   //派生类
{
public:
	void foo()  //隐藏
	{
		cout << 3 << endl;
	}
	void fun()  //重写 
	{
		cout << 4 << endl;
	}
};
int main(void)
{
	A a;
	B b;
	A *p = &a; //指向A(基类)
	p->foo();  // 调用A(基类)的foo()    输出1
	p->fun();  // 调用A(基类)的fun()    输出2

	p = &b;  // 指向B(派生类)
	p->foo(); //指向A 的foo()            输出1
	p->fun(); //指向B 的fun()            输出4
	return 0;
}



解析:其实,第一个p-->foo()  和 p-->fun() 很好理解,本身是基类,指向的也是基类的对象,调用本身的函数。
 第二个p-->foo()  和 p-->fun()  分别输出   1  4   ;   p指向的是子类对象,这就体现了多态的用法。在子类中 重写了fun()函数  ,所以调用重写后的fun()函数。   p--->fun()  调用过程:p->fun()指针是基类指针,指向的fun是一个虚函数,由于每个虚函数都有一个虚函数列表,此时p调用fun()并不是直接调用函数,而是通过虚函数列表找到相应的函数的地址,因此根据指向的对象不同,函数地址也将不同,这里将找到对应的子类的fun()函数的地址,因此输出的结果也会是子类的结果4。

上面的测试方法还可以换成 : B*ptr = (B*)&a ;    ptr->foo() ;    ptr->fun();  这也很好理解,将基类对象强制转换成派生类对象,但是这样可能导致访问超过基类的大小时,会崩溃的。







  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值