zoukankan      html  css  js  c++  java
  • C++多态的使用

    一、多态有静态多态和动态多态:

    1、静态多态:函数重载和运算符重载属于静态多态,复用函数名

    2、动态多态:派生类和虚函数实现运行时多态

    二、静态多态和动态多态的区别

    1、静态多态函数地址早绑定:在编译阶段确定函数地址

    2、动态多态的函数地址晚绑定:运行阶段确定函数地址

    三、动态多态满足条件

    1、有继承关系

    2、子类重写父类虚函数

    四、动态多态的使用

    父类的指针或者引用 执行子类对象

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 5;
    class Animal
    {
    public:
        virtual void speak()
        {
            printf("Animal is Speaking
    ");
        }
    };
    class dog : public Animal
    {
    public:
        virtual void speak()    //这里的virtual可写可不写
        {
            printf("dog is Speaking
    ");
        }
    };
    class cat : public Animal
    {
    public:
        virtual void speak()    //这里的virtual可写可不写
        {
            printf("cat is Speaking
    ");
        }
    };
    void test1(Animal &a)
    {
        a.speak();
    }
    void test2(Animal *a)
    {
        a->speak();
    }
    int main()
    {
        dog g;
        cat t;
        test1(t);
        dog * ptr = &g;
        test2(ptr);
        return 0;
    }

    多态原理:

    如果把上面main函数内容换成

    
    
    class Animal
    {
    public:
        void speak()
        {
            printf("Animal is Speaking ");
        }
    };
    int main()
    {
        Animal * a=NULL;
        a->speak();
        return 0;
    }
    /*
    输出:
    Animal is Speaking
    */

    上面代码说明了就算没有对变量a实例化一个对象,但是调用的方法仍然是看变量a的左边(也就是a的类型)。但是多态中我们发现变量a调用的方法实际上和a的类型无关,这一点就需要把函数变成虚函数,也就是在函数前面加上关键字virtual。

    例如Animal类,当它内部的speak函数不是虚函数的时候,你的sizeof(Animal)的值是等于1的(因为方法和变量是分开存储的,而且Animal类没有成员变量,这就相当于Animal是一个空对象)。但是当内存speak函数是虚函数的时候,你的sizeof(Animal)的值是等于4或者8(这要看操作系统,因为实际上这个时候类内部会出现一个指针vfptr(virtual function pointer 虚拟函数表指针),在32位操作系统上指针占4个字节)。

    vfptr会指向一个虚拟函数表(vftable),虚拟函数表里面记录的是这个类的虚函数的地址

    我们使用visual studio查看类信息:

    当我们的cat类没有重写Animal的speak方法时(这个时候会把父类的东西都继承过来):

    当cat类重写Animal的speak方法时:

    我们接着对之前那个代码分析一下:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 5;
    class Animal
    {
    public:
        virtual void speak() //这多加了virtual
        {
            printf("Animal is Speaking
    ");
        }
    };
    int main()
    {
        Animal * a=NULL;
        a->speak();
    }

    这个代码的输出是什么也没有,为什么不加virtual就有输出,加了就没有输出呢?

    我认为加了virtual之后函数变成了虚函数,这个时候类内部会出现一个指针vfptr,但是你实例化的时候给a指针赋了一个NULL指针,也就是没有给a分配内存,那么vfptr指针就没有了,也就没办法找到vftable,也就没办法找到函数入口地址。(这是我认为的,不知道对不对,如果有错的话,希望大家给我指出^_^)

  • 相关阅读:
    perl Exporter一些神奇写法
    perl eval函数
    hibernate 映射文件配置默认值方法
    JavaWeb 服务启动时,在后台启动加载一个线程。
    根据input 标签取value属性的值
    perl 继承小例子
    net.sf.json.JSONException: Found starting '{' but missing '}' at the end. at character 0 of null
    Uncaught TypeError: Cannot read property 'plugin' of undefined
    mysql 密码过期问题 password_expired

  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/14724847.html
Copyright © 2011-2022 走看看