C++——多态

多态:

具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。

多态的构成条件:

  • 必须通过基类的指针或者引用调用虚函数
  • 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写

虚函数:

多态是实现是依赖于虚函数来实现的,之所以虚函数可以分清楚当前调用的函数是基类的还是派生类的,主要在于基类和派生类分别有着自己的虚函数表,再调用虚函数时,它们是通过去虚函数表去对应的函数的。 即被virtual修饰的类成员函数称为虚函数。

虚函数的重写:

虚函数的重写(覆盖):派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数返回值类型、函数名字、参数列表完全相同),称子类的虚函数重写了基类的虚函数。

class Person { 
    public:    
    virtual void BuyTicket() 
    { 
        cout << "Hello World!" << endl;
    } 
};
#include<iostream>
using namespace std;


class A
{
public :
     void print()
    {
         cout << "A" << endl;
    }
    virtual void print1()
    {
        cout << "Virtual A" << endl;
    }

};

class B:public A{
public:
    void print() { cout << "B" << endl; }
    virtual void print1() { cout << "Virtual B" << endl; }
};

void fn(A & s)
{
    s.print();
    s.print1();
}
int main()
{

    A a;
    B b;
    fn(a);
    fn(b);
    return 0;
}

结果是:

A   Virtual A     B    Virtual B

这时候程序就知道当前就指导调用什么函数。 

其实虚函数表的本质就是一种迟后联编的过程,正常编译都是先期联编的,但是当代码遇到了virtual时,就会把它当做迟后联编,但是为了迟后编译,我么就生成了局部变量–虚函数表,这就增大了一些空间上的消耗。(前提是两个函数的返回类型,参数类型,参数个数都得相同,不然就起不到多态的作用)

#include<iostream>
#include<cmath>
using namespace std;

class A
{
public :
    virtual void fun(int x)
    {
        cout << "A:  " << x << endl;
    }
};
class B :public A
{
public :
    virtual void fun(float x)
    {
        cout << "B: " << x << endl;
    }
};

void test(A & x)
{
    int i = 1;
    x.fun(i);
    float a = 2.0;
    x.fun(a);
}


int main()
{
    A a;
    B b;
    test(a);
    test(b);
    return 0;
}

结果是:A:1    A:2    A:1    A:2    

从输出结果可以看出,fun函数并没有起到多态的作用,这里主要是因为基类和派生类的fun在编译时,被看成了两个不同函数,因为他们的参数不同。如果返回的类型不同,也会出现同样的情况,但是有一种特殊的情况,那就是如果基类中虚函数返回一个基类指针或引用,派生类中返回一个派生类的指针或引用,则c++将其视为同名虚函数而进行迟后联编。

使用虚函数的一些限制 
(1):只有类成员函数才能声明为虚函数,这是因为虚函数只适用于有继承关系的类对象中。 
(2):静态成员函数不能说明为虚函数,因为静态成员函数不受限与某个对象,整个内存中只有一个,所以不会出现混淆的情况 
(3):内联函数不可以被继承,因为内联函数是不能子啊运行中动态的确认其位置的。 
(4):构造函数不可以被继承。 
(5):析构函数可以被继承,而且通常声明为虚函数。

六、纯虚函数 
(1):解释 
虚函数是在基类中被声明为virtual,并在派生类中重新定义的成员函数,可实现成员函数的动态重载 
纯虚函数的声明有着特殊的语法格式:virtual 返回值类型成员函数名(参数表)=0; 
 (2):必要性: 
在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;),则编译器要求在派生类中必须予以重载以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。 
 (3):抽象类的解释 
包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象。 
在C++中,抽象类只能用于被继承而不能直接创建对象的类(Abstract Class)。

函数的隐藏和覆盖:

  • 函数的隐藏:没有定义多态的情况下,即没有加virtual的前提下,如果定义了父类和子类,父类和子类出现了同名的函数,就称子类的函数把同名的父类的函数给隐藏了。
  • 函数的覆盖:是针对多态来说的。如果定义了父类和子类,父类中定义了公共的虚函数,如果此时子类中没有定义同名的虚函数,那么在子类的虚函数表中将会写上父类的该虚函数的函数入口地址,如果在子类中定义了同名虚函数的话,那么在子类的虚函数表中将会把原来的父类的虚函数地址覆盖掉,覆盖成子类的虚函数的函数地址,这种情况就称为函数的覆盖

本文借鉴原博客:https://blog.youkuaiyun.com/qq_35644234/article/details/52825311

内容概要:本文档详细介绍了基于事件触发扩展状态观测器(ESO)的分布式非线性车辆队列控制系统的实现。该系统由N+1辆车组成(1个领头车N个跟随车),每辆车具有非线性动力学模型,考虑了空气阻力、滚动阻力等非线性因素及参数不确定性外部扰动。通过事件触发ESO估计总扰动,基于动态面控制方法设计分布式控制律,并引入事件触发机制以减少通信计算负担。系统还包含仿真主循环、结果可视化等功能模块。该实现严格遵循论文所述方法,验证了观测误差有界性、间距误差收敛性等核心结论。 适合人群:具备一定编程基础,对非线性系统控制、事件触发机制、扩展状态观测器等有一定了解的研发人员研究人员。 使用场景及目标:①研究分布式非线性车辆队列控制系统的理论与实现;②理解事件触发机制如何减少通信计算负担;③掌握扩展状态观测器在非线性系统中的应用;④学习动态面控制方法的设计与实现。 其他说明:本文档不仅提供了详细的代码实现,还对每个模块进行了深入解析,包括非线性建模优势、ESO核心优势、动态面控制与传统反步法对比、事件触发机制优化等方面。此外,文档还实现了论文中的稳定性分析,通过数值仿真验证了论文的核心结论,确保了系统的稳定性有效性。建议读者在学习过程中结合代码进行实践,并关注各个模块之间的联系与相互作用。
内容概要:本文档《c预约面试大全.pdf》汇集了大量C语言及其相关领域的面试问题与解答,涵盖了从基础概念到高级技巧的广泛知识点。主要内容包括但不限于:C语言的基础语法(如static关键字的作用、指针引用的区别)、数据结构(如平衡二叉树、链表操作)、算法(如冒泡排序的时间复杂度)、计算机网络(如TCP/IP协议栈)、操作系统(如进程线程的区别)、内存管理(如堆栈差异)等方面。此外,还涉及了一些较为复杂的主题,例如位域的应用、编译原理中的预编译概念、以及针对特定问题的编程实现(如寻找数组中的重复数字、实现约瑟夫环问题等)。每个问题都配有详细的解释代码示例,旨在帮助求职者全面准备C语言相关的技术面试。 适合人群:正在准备C语言及相关领域(如嵌入式开发、系统编程)工作的求职者,尤其是有一定编程基础但缺乏实战经验的技术人员。 使用场景及目标:①帮助读者深入理解C语言的核心概念技术细节;②通过实际案例分析提升解决复杂问题的能力;③为参加各技术面试做好充分的知识储备心理准备。 其他说明:此文档不仅包含了理论知识,还提供了大量实战练习的机会,鼓励读者动手实践,从而更好地掌握所学内容。同时,文档中的问题难度逐步递增,适合不同层次的学习者按需选择。由于C语言是许多高级编程语言的基础,因此这份资料对于想要深入学习计算机科学的学生也非常有价值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值