众所周知C++是一种面向对象的语言,它相较于C语言还是主要它的封装、继承、多态;今天我们就来说说它的多态。
多态是什么呢?说白了就是同一操作,用作不同对象,可以产生不同的效果。
关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议。
然后有人就要问了,那多态有什么用呢?多态其实可以减少代码量。比如你要一个不同子类产生不同的效果,那你是不是要先去判断这个对象应该用哪个函数,那你是不是要不停的if来判断,但是使用多态就可以合理的解决这个问题了。
多态分为静多态(函数重载,模板)和动多态(虚函数)
静多态:在编译器的编译期间完成,编译器根据实参类型来选择调用合适的函数,如果有合适的函数就调用,没有就发出警告或报错。
动多态:实在程序运行时根据基类的引用(指针)指向的对象1确定自己具体应该调用哪个类的虚函数
动多态的条件:
基类必须包含虚函数,并且派生类中一定要对基类的虚函数进行重写
通过基类对象的指针或者引用调用虚函数
函数重载:重载函数是函数的一种特殊情况,为方便使用,C++允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同,也就是说用同一个函数完成不同的功能。这就是重载函数。重载函数常用来实现功能类似而所处理的数据类型不同的问题。不能只有函数返回值类型不同。
函数模板:函数模板不是一个实在的函数,编译器不能为其生成可执行代码。定义函数模板后只是一个对函数功能框架的描述,当它具体执行时,将根据传递的实际参数决定其功能。
我们今天主要来说说虚函数:虚函数其实就是对函数的重写,要求函数名,函数类型,参数个数和参数类型相同,但析构函数可以不同,析构函数在底层其实也会将函数名同步。
下面我们来说说虚函数表:对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其容真实反应实际的函数。这样,在有虚函数的类的实例中这个表被分配在了这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样,指明了实际所应该调用的函数。
至于有人不太懂这个虚函数表,虚函数指针,什么的,给你一张图你就清楚了

在这里还有必要说说纯虚函数,纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”
为什么会有纯虚函数呢?
1、为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。
2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。
为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;),则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。它的存在就是为了被继承,这样就很好地解决了上述两个问题。
下面附上多态的代码,可以看代码来了解这些东西
#include<iostream>
using namespace std;
//class Person
//{
//public:
// virtual void BuyTicket() { cout << "免票-全价" << endl; }
//};
//class Student:public Person
//{
//public:
// virtual void BuyTicket() { cout << "免票-半价" << endl; }
//
//};
//void Func(Person& p)
//{
// p.BuyTicket();
//}
//int main()
//{
// Person ps;
// Student st;
// Func(ps);
// Func(st);
// return 0;
//
//}
/////////////////////////////////
//class Person
//{
//public:
// virtual ~Person() { cout << "~Person" << endl; }
//};
//class Student:public Person
//{
// virtual ~Student() { cout << "~Student" << endl; }
//
//};
//int main()
//{
// Person* p1 = new Person;
// Person* p2 = new Student;
// delete p1;
// delete p2;
// return 0;
//
//}
/////////////////////纯虚函数不能实例化对象,必须被重写
//class car
//{
//public:
// virtual void Drive();
//};
//class benz :public car
//{
// //virtual void Drive()override
// virtual void Drive()
// {
// cout << "舒适" << endl;
// }
//};
//class bmw :public car
//{
// virtual void Drive()
// {
// cout << "操控" << endl;
// }
//};
//void Test()
//{
// car* p = new benz;
// p->Drive();
// car* p1 = new bmw;
// p1->Drive();
//
//
//}
//int main()
//{
// Test();
// return 0;
//}
//override 修饰派生类虚函数强制完成重写
class Base
{
public:
virtual void Func1()
{
cout << "Base::Func1()" << endl;
}
virtual void Func2()
{
cout << "Base::Func2()" << endl;
}
void Func3()
{
cout << "Base::Func3()" << endl;
}
private:
int _b = 1;
};
class Derive : public Base
{
public:
virtual void Func1()
{
cout << "Derive::Func1()" << endl;
}
private:
int _d = 2;
};
//void Test(Base &p)
//{
// p.Func1();
//}
int main()
{
Base b;
b.Func1();
Derive d;
d.Func3();
return 0;
}
//不构成多态
755

被折叠的 条评论
为什么被折叠?



