多态

    xiaoxiao2023-11-21  169

    什么是多态

    字面意思就是多种形态,当类之间存在层次结构,通过继承来相互关联时,就会用到多态。多态意味着在调用成员时,会根据调用的函数的对象来执行不同的函数。通俗一点就是同一操作作用于不同的对象,可以产生不同的效果。

    C++中的多态性具体体现在运行和编译两个方面。运行时多态是动态多态,其具体引用的对象在运行时才能确定。编译时多态是静态多态,在编译时就可以确定对象使用的形式。

    静态多态

    在编译期间完成的,编译器会根据实参的类型去选择调用适合的函数。典型的一种就是函数重载

    动态多态

    在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。虚函数

    多态成立的三个条件

    1、要有继承

    2、要有函数重写  虚函数

    3、要有父类指针(引用) 指向子类对象

    多态是设计模式的基础,多态是框架的基础

    1、C++中通过virtual关键字对多态进行支持

    2、使用virtual声明的函数被重写后即可展现多态特性

    class Cat { public: virtual int Power(){return 10;} }; class Cat1 :public Cat { public: virtual int Power(){return 20;} }; class Cat2 :public Cat { public: virtual int Power(){return 30;} }; class Mouse { public: int Power(){return 25;} }; void PlayTest(Cat &c,Mouse &m) { if (c.Power() < m.Power()) { cout <<"老鼠跑了" << endl; } else { cout <<"老鼠挂了" << endl; } } //main { Cat1 c1; Cat2 c2; Mouse m; PlayTest(c1, m); PlayTest(c2,m); }

    调用结果:

    上面的例子中通过比较老鼠和猫之间的力量悬殊,来展示同一种动物的不同状态。在测试阶段传入不同对象根据条件来调用对应的函数。

    那么virtual 在这里起到了一个什么作用呢?首先,之前分析过重写(存在继承的父类和子类中有相同函数名的方法),子类中定义了和父类中相同的函数(方法名相同),就是说子类重写了父类的方法。这种情况下,父类中被重写的函数依然会继承给子类,默认情况下子类中重写的函数将隐藏父类中的函数,我们可以通过类名去访问被隐藏的函数。

    举个例子了解一下virtual的作用:

    #include <iostream> using namespace std; #pragma warning(disable : 4996) class Animal { public: virtual void Call() { cout << "Animal: Call" << endl; } void Eat() { cout << "Animal: Eat" << endl; } }; class Cat:public Animal { public: virtual void Call() { cout << "Cat: Call" << endl; } void Eat() { cout << "Cat: Eat" << endl; } }; void Action(Animal &al) { al.Call(); al.Eat(); } void PlayObj() { Animal al; Cat c; Action(al); Action(c); } int main() { PlayObj(); system("pause"); return 0; }

    调用结果:

    这里我们是通过父类的引用来调用(父类引用可以直接引用子类对象),可以看出在没有使用virtual加以说明时,子类重写了父类的方法并使其隐藏,因此调用的时候会根据对象来对应调用。而用virtual说明后相当于重定义,传入对象后编译器会根据对象的Vptr指针,在所指的虚函数表中查找对应函数函数,并调用。可以去看多态原理探究

    为什么要会用到多态

    面向对象的三大概念:封装、继承、多态

    封装:突破了C语言函数的概念。

    继承:代码复用,使用原来写好的代码,提高效率

    多态:易于扩展,可维护性高,实际开发中,提倡扩展不提倡修改。

    多态相关面试题

    面试题1:请谈谈你对多态的理解

    多态的实现效果

    多态:同样的调用语句有多种不同的表现形态;

    多态实现的三个条件

    有继承、有virtual重写、有父类指针(引用)指向子类对象。

    多态的C++实现

    virtual关键字,告诉编译器这个函数要支持多态;不是根据指针类型判断如何调用;而是要根据指针所指向的实际对象类型来判断如何调用多态的理论基础

    态联编PK静态联编。根据实际的对象类型来判断重写函数的调用。

    多态的重要意义

    设计模式的基础 是框架的基石。

    实现多态的理论基础 

    函数指针做函数参数

    C函数指针是C++至高无上的荣耀。C函数指针一般有两种用法(正、反)。

    多态原理探究

    与面试官展开讨论

     

    面试题2:是否类的每个成员函数都声明为虚函数,为什么。

    不能声明为虚函数: 普通函数(非成员函数)、静态成员函数、内联成员函数、构造函数、友元函数。析构函数可以是虚的,而且通常声明为虚函数。

    普通函数(非成员函数)

    只能被重载,不能被重写,在类的外部什么为虚函数也没什么意思。

    静态成员函数

    对于每个类来说只有一份,所有的对象都共享这个函数,不归某个对象所有,因此也没必要。

    内联成员函数

    其作用是在调用的位置直接展开,减少函数调用的开销。属于编译时执行,而虚函数是为了在继承后对象能够准确的执行自己的动作,是在运行时才绑定函数。

    构造函数

    是用来初始化类的对象的,只有在对象生成后才能发挥多态作用。如果构造函数声明为虚的,则表现为在对象还没生成的时候来定义它,则会出现编译错误。另外,构造函数不能被继承。

    友元函数

    它不属于类的成员函数,不能被继承。

    面试题3:构造函数中调用虚函数能实现多态吗?为什么?

    首先要明白虚函数的调用原理,它是通过对象的vptr指针来对虚函数表的检查和调用,那么就需要先初始化类的对象。谁在前谁在后?

    请点击构造函数中能调用虚函数,能实现多态吗?

    面试题4:为什么要定义虚析构函数?

     

    最新回复(0)