多态浅析(静态多态,动态多态)

多态

多态
多态分为动态多态和静态多态。
静态多态:在运行前就决定函数调用的地址,也就是地址早绑定。
静态多态包括了:函数重载,运算符重载,和重定义。

分别阐述一下:

函数重载首先在同一个作用域当中,函数的名字相同,但是函数的参数不同(类型,个数,顺序)

void func(void)
{
	cout<<"good! 没有参数"<<endl;
}


void func(int val)
{
	cout<<"good! 一个int类型参数"<<endl;
}


void func(int val,char ch)
{
	cout<<"good! 两个参数"<<endl;
}

上面的三个函数就是函数重载,函数名一样,但是参数不同。

调用的时候,func(3),则函数的参数自动推导为int,使用的第二个函数,输出为good! 一个int类型参数
调用的时候,func(),则函数的参数自动推导为void,使用的第二个函数,输出为good! 没有参数

以此类推。

运算符重载

#include<iostream> 
using namespace std;
 #include<string> 
 class Person 
 {
 	public: 
 	Person(){} 
 	Person(string name, int age) 
 	{ 
 		this->m_Name = name; 
 		this->m_Age = age; 
 	}
 	// 重 载 == 
 	bool operator==(const Person& p) 
 	{ 
 		if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) 
 			return true; 
 		return false;
 	 }
 public: 
 	string m_Name; 
 	int m_Age; 
 };

在这里为了使用方便,就将数据设置为共有了。重载了==,方便判断两个Person 类型的数据时候相同,如果没有重载这个运算符那是必然会报错,因为系统不知道这个自定义的类型如何进行比较。

重载运算符的时候,先看运算符的两端有几个对象,特别是运算符的左边,如果是对象的话,尽量使用成员函数来完成函数的重载,如果左边不是对象的话,那就只能使用全局函数进行函数重载了。这个时候如果运算符的右边是对象的话,就要使用friend在类中声明,使用friend函数严重破坏了类的封装性,friend这个关键字是在太厉害了,有点像一个bug,无视权限,只要用这个在类中声明友元类,这个函数都可以进行访问。

重定义与重写
这两个都是发生在继承中,都是将父类的函数进行改变:
如果父类函数中没有virtual关键字修饰,这个时候子类对父类的这个函数进行重定义,这个类似于重载,只要函数名相同,就可以,重定义完成就可以将父类的同名函数屏蔽。(只是屏蔽,还是可以进行访问,使用作用域!)

如果父类的这个函数用virtual关键字修饰,称之为虚函数,当有这个关键字修饰的时候,都会产生一个虚函数指针,这个指针指向一个虚指针函数表,表中记载着虚函数的入口地址。这个时候子函数对其继承,会将这个虚函数指针继承,这个表也会被继承过来。

当子函数对这个用virtual关键字修饰的函数进行重写,就必须要与这个函数的返回值,参数,函数名完全相同,对函数体进行改变。这个时候再加上父类的指针指向子类的空间,那就可以实现动态多态了~
总结一下:

  1. 使子类继承父类“虚函数表指针” ----> 该“虚函数表指针”既可以指向父类“虚函数 表”也可以指向子类“虚函数表”.
  2. 子类重写父类虚函数:如果不重写,子类“虚函数表”仍然维护父类函数,重写后,子类更新自身的“虚函数表”,维护子类函数.
  3. 父类指针或引用,指向子类对象:使继承的“虚函数表指针”指向子类的虚函数表.

这三步就可以实现动态多态了!
实例:

#include<iostream>
 using namespace std;
 class Animal
 {
 public: 
 	virtual void speak() 
	 { cout << "动物在说话" << endl; }
	 void eat(int a) 
 	{ cout << "动物在吃饭" << endl; } 
 }; 
 class Cat :public Animal 
 {public: 
 	virtual void speak()
 	{ cout << "小猫在说话" << endl; }
 	void eat(int a) 
 	{ cout << "小猫在吃饭" << endl; }
 };
 int main() 
 { 
 	Animal * cat = new Cat; 
 	cat->speak(); // 结果:小猫在说话 
 	cat->eat(0); // 结果:动物在吃饭 
 	
 	return 0; 
}

谢谢大家看到这里,这个多态的知识点还是挺多的,我写的还是不全面,但是我会在这个帖子,继续往这个里面进行补充。

如果大家觉得有什么不对,或者有什么问题在下面留言留言就好,我会尽快回复!

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值