• C++中对C的扩展学习新增内容———面向对象(继承)函数扩展性及虚函数机制


    1、c语言中的多态,动态绑定和静态绑定

    void do_speak(void(*speak)())
    {
        speak();
    }
    
    void pig_speak()
    {
        cout << "猪叫..." << endl;
    }
    
    void cat_speak()
    {
        cout << "猫叫..." << endl;
    }
    
    void test01()
    {
        do_speak(cat_speak);
    }

    C++中的多态:

    class Animal
    {
    public:
        // 虚函数
        virtual void speak()
        {
            cout << "动物在叫唤..." << endl;
        }
    
        void func()
        {
        
        }
    };
    
    
    class Cat : public Animal
    {
    public:
        Cat(string name)
        {
            m_name = name;
        }
    
        void speak()
        {
            cout << m_name << " 在叫唤..." << endl;
        }
    
        void func()
        {
    
        }
    public:
        string m_name;
    };
    
    
    class Dog : public Animal
    {
    public:
        Dog(string name)
        {
            m_name = name;
        }
    
        void speak()
        {
            cout << m_name << " 在汪汪..." << endl;
        }
    
        void func()
        {
    
        }
    public:
        string m_name;
    };
    
    
    class Pig : public Animal
    {
    public:
        void speak()
        {
            cout << " 猪在叫..." << endl;
        }
    };

    1、静态绑定

      (1) 编译器会根据指针类型、引用类型来确定函数调用。

      (2) 如果要实现根据传递不同对象,调用不同对象的speak,就要进行动态绑定。

    2、动态绑定

      (1) 根据引用或者指针,实际指向的类型来确定函数调用。

      (2) 虚函数机制可以让编译器实现动态绑定。

    3、实现多态的条件

      (1) 表现形式:父类指针或者引用指向子类对象。

      (2) 父类必须要有虚函数。

      (3) 子类必须重写父类的虚函数,如果不重写,默认调用的父类函数。

      (4) 父类纸质恩、或者引用指向子类对象。

    虚函数的机制:

    1、如果类的内部包含了虚函数,编译器首先会在类中安插虚函数表指针vfptrvfptr指向一张表,这张表中存储的类中所有的虚函数入口地址。

    2、当子类继承了父类,会将父类的虚函数表指针继承下来。一开始该虚函数指针指向父类的虚函数表,在子类中的构造函数中,编译器将其重新指向到了子类自己的虚函数表。

    3、当子类重写了父类的虚函数,在虚函数表中会用子类的虚函数地址去覆盖父类对应虚函数的函数地址。

    4、当通过父类指针、引用调用函数时,编译器会先找到该对象中隐藏存储的vfptr指针,根据虚函数指针找到虚函数表,在虚函数表中找到对应的函数入口地址,进行执行。

    虚函数代码实现:

    class Animal
    {
    public:
        // 虚函数
        virtual void speak()
        {
            cout << "动物在叫唤..." << endl;
        }
    
        void func()
        {
        
        }
    };
    
    
    class Cat : public Animal
    {
    public:
        Cat(string name)
        {
            m_name = name;
        }
    
        void speak()
        {
            cout << m_name << " 在叫唤..." << endl;
        }
    
        void func()
        {
    
        }
    public:
        string m_name;
    };
    
    
    class Dog : public Animal
    {
    public:
        Dog(string name)
        {
            m_name = name;
        }
    
        void speak()
        {
            cout << m_name << " 在汪汪..." << endl;
        }
    
        void func()
        {
    
        }
    public:
        string m_name;
    };
    
    
    class Pig : public Animal
    {
    public:
        void speak()
        {
            cout << " 猪在叫..." << endl;
        }
    };
  • 相关阅读:
    把EXE可执行文件等作为资源包含在Delphi编译文件中
    delphi怎么做桌面滚动文字?
    cxGrid控件过滤筛选后如何获更新筛选后的数据集
    我的ecshop二次开发经验分享
    ECSHOP 数据库结构说明 (适用版本v2.7.3)
    cxGrid 怎样才能让不自动换行 WordWrap:=false
    vi notes
    ODI中显示us7ascii字符集的测试
    ODI 11g & 12c中缓慢变化维(SCD)的处理机制
    ODI中的临时接口
  • 原文地址:https://www.cnblogs.com/yyslif/p/11892400.html
Copyright © 2020-2023  润新知