多态
多态分为动态多态和静态多态。
静态多态:在运行前就决定函数调用的地址,也就是地址早绑定。
静态多态包括了:函数重载,运算符重载,和重定义。
分别阐述一下:
函数重载首先在同一个作用域当中,函数的名字相同,但是函数的参数不同(类型,个数,顺序)
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关键字修饰的函数进行重写,就必须要与这个函数的返回值,参数,函数名完全相同,对函数体进行改变。这个时候再加上父类的指针指向子类的空间,那就可以实现动态多态了~
总结一下:
- 使子类继承父类“虚函数表指针” ----> 该“虚函数表指针”既可以指向父类“虚函数 表”也可以指向子类“虚函数表”.
- 子类重写父类虚函数:如果不重写,子类“虚函数表”仍然维护父类函数,重写后,子类更新自身的“虚函数表”,维护子类函数.
- 父类指针或引用,指向子类对象:使继承的“虚函数表指针”指向子类的虚函数表.
这三步就可以实现动态多态了!
实例:
#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;
}
谢谢大家看到这里,这个多态的知识点还是挺多的,我写的还是不全面,但是我会在这个帖子,继续往这个里面进行补充。
如果大家觉得有什么不对,或者有什么问题在下面留言留言就好,我会尽快回复!