这篇博客简单介绍了多态的概念,分类,动态多态实现的条件,重写等几个方面,希望能够加深对于多态的理解。
1.概念
多态:指的是同一个事物的多种表现形态
2.多态的分类
分为:
1)静态多态:编译器在编译期间来确定程序的行为(确定具体调用哪个函数)
a)函数重载
b)泛型编程
2)动态多态:在程序运行时,根据基类的指针(引用)指向的对象来确定调用哪个类的虚函数
3.代码实现一个多态,多态的例子
我们实现一个基类是student,派生类为graduate
class Student
{
public:
//构造函数
Student(int n, string name, float score)
:_num(n)
, _name(name)
, _score(score)
{};
//输出函数
virtual void Display()
{
cout << "num:" << _num << endl;
cout << "name:" << _name << endl;
cout << "score:" << _score << endl;
}
protected:
int _num;
string _name;
float _score;
};
class Graduate :public Student
{
public:
//构造函数
Graduate(int n, string name, float score, float p)
:Student(n, name, score)
, _pay(p)
{};
//对基类的Display进行重写
virtual void Display()
{
cout << "num:" << _num << endl;
cout << "name:" << _name << endl;
cout << "score:" << _score << endl;
cout << "pay:" << _pay << endl;
}
protected:
float _pay;
};
void TestVirtualFunc(Student& s,const string str)
{
cout << str << endl;
s.Display();
cout << endl;
}
int main()
{
Student s(1,"张三",90);
Graduate g(2,"李四",80,100);
TestVirtualFunc(s,"Student:");
TestVirtualFunc(g,"Graduate:");
return 0;
}
结果:实现了调用同一个函数结果不同的情况,这就是多态
4.动态多态实现的条件
1)基类中必须包含虚函数,并且派生类中一定要对基类中的虚函数进行重写
2)通过基类对象的指针或者引用调用虚函数
那么什么是重写呢?
如下代码:
class Base
{
public:
virtual void Func1()
{
cout << "Base::Func1" << endl;
}
virtual void Func2()
{
cout << "Base::Func2()" << endl;
}
void Func3()
{
cout << "Base::Func3()" << endl;
}
virtual void Func4()
{
cout << "Base::Func4()" << endl;
}
};
class Derived:public Base
{
public:
virtual void Func1()
{
cout << "Derived::Func1()" << endl;
}
//基类的Func2中有virtual,派生类中没有
void Func2()
{
cout << "Derived::Func2()" << endl;
}
//基类的Func3中没有virtual,派生类中有
virtual void Func3()
{
cout << "Derived::Func3()" << endl;
}
//基类和派生类的参数列表不一致
virtual void Func4(int)
{
cout << "Derived::Func4()" << endl;
}
};
//通过基类的引用来调用虚函数
void TestVirtualFunc(Base& b,const string& str)
{
cout << str << endl;
b.Func1();
b.Func2();
b.Func3();
b.Func4();
cout << endl;
}
int main()
{
Base b;
Derived d;
TestVirtualFunc(b,"Base:");
TestVirtualFunc(d,"Derived");
return 0;
}
运行结果:
如图:函数Func1和Func2构成了多态,Func3和Func4未构成多态,原因是不满足构成多态的条件1,没有构成重写,那么什么是重写呢?
5.重写
重写要满足以下几个条件:
a)基类中的函数必须为虚函数
b)派生类中重写的虚函数必须与基类的虚函数原型保持一致(返回值,函数名字,参数列表)
例外:
(1)协变:返回值类型不同,
基类中的虚函数返回基类对象的指针(引用)
派生类的虚函数返回派生类对象的指针(引用)
这种情况也会产生重写
如下代码:
在Base类中新增加Func3函数
virtual Base& Func3()
{
cout << "Base::Func3()" << endl;
return *this;
}
在Derived中新增加Func3函数:
virtual Derived& Func3()
{
cout << "Derived::Func3()" << endl;
return *this;
}
结果:Func3构成了重写,满足了多态的条件,这个例子就是协变
(2)析构函数:基类和派生类的函数名字不同,这种情况也会产生重写
c)基类的虚函数和派生类的虚函数访问限定符可以不同
【面试题】
什么是函数重载,同名隐藏和重写?