• 详解C++静态多态和动态多态的区别


    目录

    1.多态的概念与分类

    2.多态的作用

    3.静态多态

    4.动态多态

    5.总结


    1.多态的概念与分类

            多态(Polymorphisn)是面向对象程序设计(OOP)的一个重要特征。多态字面意思为多种状态。在面向对象语言中,一个接口,多种实现即为多态。C++中的多态性具体体现在编译和运行两个阶段。编译时多态是静态多态,在编译时就可以确定使用的接口。运行时多态是动态多态,具体引用的接口在运行时才能确定。

    图片

            静态多态和动态多态的区别其实只是在什么时候将函数实现和函数调用关联起来,是在编译时期还是运行时期,即函数地址是早绑定还是晚绑定的。静态多态是指在编译期间就可以确定函数的调用地址,并生产代码,这就是静态的,也就是说地址是早绑定。静态多态往往也被叫做静态联编。动态多态则是指函数调用的地址不能在编译器期间确定,需要在运行时确定,属于晚绑定,动态多态往往也被叫做动态联编。


    2.多态的作用

            为何要使用多态呢?封装可以使得代码模块化,继承可以扩展已存在的代码,他们的目的都是为了代码重用。而多态的目的则是为了接口重用。静态多态,将同一个接口进行不同的实现,根据传入不同的参数(个数或类型不同)调用不同的实现。动态多态,则不论传递过来的哪个类的对象,函数都能够通过同一个接口调用到各自对象实现的方法。


    3.静态多态

            静态多态往往通过函数重载和模板(泛型编程)来实现,具体可见下面代码:

    1. #include
    2. using namespace std;
    3. //两个函数构成重载
    4. int add(int a, int b)
    5. {
    6. cout<<"in add_int_int()"<
    7. return a + b;
    8. }
    9. double add(double a, double b)
    10. {
    11. cout<<"in add_double_doube()"<
    12. return a + b;
    13. }
    14. //函数模板(泛型编程)
    15. template <typename T>
    16. T add(T a, T b)
    17. {
    18. cout<<"in func tempalte"<
    19. return a + b;
    20. }
    21. int main()
    22. {
    23. cout<<add(1,1)<//调用int add(int a, int b)
    24. cout<<add(1.1,1.1)<//调用double add(double a, double b)
    25. cout<<add<char>('A',' ')<//调用模板函数,输出小写字母a
    26. }

            程序输出结果:

    1. in add_int_int()
    2. 2
    3. in add_double_doube()
    4. 2.2
    5. in func tempalte
    6. a

    4.动态多态

            动态多态最常见的用法就是声明基类的指针,利用该指针指向任意一个子类对象,调用相应的虚函数,可以根据指向的子类的不同而调用不同的方法。如果没有使用虚函数,即没有利用C++多态性,则利用基类指针调用相应函数的时候,将总被限制在基类函数本身,而无法调用到子类中被重写过的函数。因为没有多态性,函数调用的地址将是一定的,而固定的地址将始终调用同一个函数,这就无法“实现一个接口,多种实现”的目的了。

    1. #include
    2. using namespace std;
    3. class Base
    4. {
    5. public:
    6. virtual void func()
    7. {
    8. cout << "Base::fun()" << endl;
    9. }
    10. };
    11. class Derived : public Base
    12. {
    13. public:
    14. virtual void func()
    15. {
    16. cout << "Derived::fun()" << endl;
    17. }
    18. };
    19. int main()
    20. {
    21. Base* b=new Derived; //使用基类指针指向派生类对象
    22. b->func(); //动态绑定派生类成员函数func
    23. Base& rb=*(new Derived); //也可以使用引用指向派生类对象
    24. rb.func();
    25. }

            程序输出结果:

    1. Derived::fun()
    2. Derived::fun()

            通过上面的例子可以看出,在使用基类指针或引用指向子类对象时,调用的函数是子类中重写的函数,这样就实现了运行时函数地址的动态绑定,即动态联编。动态多态是通过“继承+虚函数”来实现的,只有在程序运行期间(非编译期)才能判断所引用对象的实际类型,根据其实际类型调用相应的方法。具体格式就是使用virtual关键字修饰类的成员函数时,指明该函数为虚函数,并且派生类需要重新实现该成员函数,编译器将实现动态绑定。


    5.总结

            应用形式上:

            静态多态是发散式的,让相同的实现代码应用于不同的场合。

            动态多态是收敛式的,让不同的实现代码应用于相同的场合。

            思维方式上:

            静态多态是泛型式编程风格,它看重的是算法的普适性。

            动态多态是对象式编程风格,它看重的是接口和实现的分离度。


    ↓↓↓更多技术内容和书籍资料获取,入群技术交流敬请关注“明解嵌入式”↓↓↓ 

  • 相关阅读:
    【Unity】简单案例脚本实现 | 鼠标观察/键盘控制移动飞行/行走/碰撞检测
    python3-函数与参数以及空值
    强化自主可控,润开鸿发布基于RISC-V架构的开源鸿蒙终端新品
    GBase 8s是如何保证数据一致性
    衡量算法的性能-时空复杂度分析
    ORA-28001:the password has expired,Linux上修改Oracle密码
    9.25day5---Qt
    Redis做缓存的几种模式以及缓存雪崩、缓存击穿、缓存穿透分别是什么,怎么解决
    用VS Code搞Qt6:编译附加模块
    NTU20220813-数据结构化和深度学习-WSL音频转发
  • 原文地址:https://blog.csdn.net/helloqusheng/article/details/133100991