zoukankan      html  css  js  c++  java
  • C++多态性(静多态和动多态)

    C++多态性

    C++中的多态(虽然多态不是C++所特有的,但是C++中的多态确实是很特殊的)分为静多态和动多态(也就是静态绑定和动态绑定两种现象),静动的区别主要在于这种绑定发生在编译期还是运行期,发生在编译期的是静态绑定,也就是静多态;发生在运行期的则是动态绑定,也就是动多态。
    静多态可以通过模板和函数重载来实现(之所说C++中的多态主要还是因为模板这个东西),下面举两个例子:
    1)函数模板
    template <typename T>
    T max(const T& lsh, const T& rhs) 
    {
           return (lsh > rhs) ? lsh : rhs;
    }
    返回两个任意类型对象的最大值(对象),前提是该类型能够使用>运算符进行比较,并且返回值是bool类型。
    使用:
    int a = 3; int b = 4;
    cout << max(a, b) << endl;
    float c = 2.4; float d = 1.2;
    cout << max(c, d) << endl;
    输出结果为:
             4
                    2.4
    这种绑定发生在编译期,这是由于模板的实例化是发生在编译期的,即在编译时编译器发现你调用max(a, b)时就自动生成一个函数
    int max(const int& lsh, const int& rhs) 
    {
           return (lsh > rhs) ? lsh : rhs;
    }
    即将所有的T替换成int;
    当你调用max(c, d)时就自动生成一个函数
    float max(const float& lsh, const float& rhs)
    {
            return (lsh > rhs) ? lsh : rhs;
    }
    之所以说开始的函数定义是函数模板,就是因为他就像个模子似的,你可以用铝作为原料也可以用石膏或者铜。
    2)函数重载:函数名相同,参数类型或个数不完全相同,返回值一样。
        函数重载不同于函数覆盖:函数覆盖指派生类重新定义基类某虚函数,参数和返回类型完全一样。
    int max (int a, int b)
    {
         return (a > b) ? a : b;
    }
    int max (int a, int b, int c)
    {
         return max(max(a, b), c);
    }
    两个函数名称一样,参数类型或个数不完全相同,返回值一样(这个不重要)。
    使用:
    int a = 3, b = 4, c = 5;
    cout << max(a, b) << endl;
    cout << max(a, b, c) << endl;
    输出结果为:
             4
                    5
    确定函数的过程也发生在编译器,当你使用max(a, b),编译器发现只有两个参数,那么就调用只有两个参数的函数版本,当使用max(a, b, c)时,编译器则使用有3个参数的版本。
    通过上面的两个例子,你还可以使用更为方便的模板函数重载:
    template <typename T>
    T max(const T& lsh, const T& rhs) 
    {
           return (lsh > rhs) ? lsh : rhs;
    }
     
    template <typename T>
    T max(const T& a, const T& b, const T& c)
    {
          return max(max(a, b), c);
    }
    使用
    float a = 3.6, b = 1.2, c = 7.8;
    cout << max(a, b, c) << endl;
    输出:
           7.8
    通过参数个数和类型,编译器自动生成和调用对应得函数版本!
     
    动多态则是通过继承、虚函数(virtual)、指针来实现(三者结合起来实现)
    函数覆盖:指派生类重新定义基类某虚函数,参数和返回类型完全一样。
    class A {
    public:
        virtual void func() const {
             coust << “A::func()” << endl;
        }
    }
     
    class B : public A {
    public: 
        virtual void func() const {
             coust << “B::func()” << endl;
        }
    }
    使用:
    A a* = B();
    a->func();
    输出:
         B::func()
    编译期是不调用任何函数的,编译器编译到a->func()时只是检查有没有语法问题,经过检查没有。编译器并不知道调用的是A版本的func()还是B版本的func(),由于a是一个指向B对象的指针,所以a只知道它指向的是一个A类型(或者能转换成A类型)的对象。通常集成体系就说明了(由于是公有继承)B是一种A。在运行期,a要调用a所指向对象的func()函数,就对它指向的对象下达调用func()的命令,结果a所指向的是一个B对象,这个对象就调用了自己版本(B版)的func()函数,所以输出时B::func()
     
    总结:
    在编译期决定你应该调用哪个函数的行为是静态绑定(static-binding),这种现象就是静多态。
    在运行期决定应该调用哪中类型对象的函数的行为是动态绑定(dynamic-binding),这种现象就是动多态!
     
    注:由于这是我花了有限的时间总结的,语言应用能力比较差,还有比如类模板(静多态和动多态组合的情况)都没有说,最近比较忙,请见谅!
     
    如果还不是很懂,我建议你看C++Primer 4th Edition,讲的比较清晰,但是比较零散!
  • 相关阅读:
    Java基础环境配置及HelloWorld
    Cassandra 在 360 的实践与改进
    如何构建阿里小蜜算法模型的迭代闭环?
    通用高效的数据修复方法:Row level repair
    RALM: 实时 Look-alike 算法在微信看一看中的应用
    人机对话技术研究进展与思考
    打造最可靠的自动驾驶基础架构
    Django中render和render_to_response的区别
    ui自动化chrome文件上传操作
    超继承super
  • 原文地址:https://www.cnblogs.com/skyofbitbit/p/2677420.html
Copyright © 2011-2022 走看看