美文网首页
多态、虚函数、虚函数表

多态、虚函数、虚函数表

作者: 叶子扬 | 来源:发表于2019-10-11 17:44 被阅读0次
    C++.png

    多态

    • 默认情况下,编译器只会根据指针类型调用对应的函数,不存在多态

    • 多态是面向对象非常重要的一个特性

      • 同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果
      • 在运行时,可以识别出真正的对象类型,调用对应子类中的函数
    • 多态的要素

      • 子类重写父类的成员函数(override)
      • 父类指针指向子类对象
      • 利用父类指针调用重写的成员函数

    虚函数

    • C++中的多态通过虚函数(virtual function)来实现
    • 虚函数:被virtual修饰的成员函数
    • 只要在父类中声明为虚函数,子类中重写的函数也自动变成虚函数(也就是说子类中可以省略virtual关键字)

    虚表

    虚函数的实现原理是虚表,这个虚表里面存储着最终需要调用的虚函数地址,这个虚表也叫虚函数表

    
    struct Animal {
        int m_age;
        virtual void speak(){
            cout << "Animal::speak()" << endl;
        }
        virtual void run(){
            cout << "Animal::run()" << endl;
        }
    };
    
    struct Cat:  Animal {
        int m_life;
        virtual void speak(){
            cout << "Cat::speak()" << endl;
        }
        virtual void run(){
            cout << "Cat::run()" << endl;
        }
    };
    
    int main() {
        Animal *cat =new Cat();
        cat->speak();
        cat->run();
        
        return 0;
    }
    // log:
    Cat::speak()
    Cat::run()
    

    注意,一定要指针,如果是对象,就失灵了。多态的三要素缺一不可。

    int main() {
        Animal cat = Cat();
        cat.speak();
        cat.run();
        
        return 0;
    }
    // log:
    Animal::speak()
    Animal::run()
    

    虚表(x86环境的图)

    调用父类的成员函数实现

    class Animal {
    public:
        virtual void speak(){
            cout << "Animal::speak()" << endl;
        }
    };
    
    class Cat: public Animal {
    public:
         void speak(){
            Animal::speak();
            cout << "Cat::speak()" << endl;
        }
    };
    
    int main() {
        Animal cat = Cat();
        cat.speak();
        
        return 0;
    }
    // log:
    Animal::speak()
    
    Q:为啥不继续执行下面的代码
    A:上面不是多态
    
    int main() {
        Animal *cat = new Cat();
        cat->speak();
        
        return 0;
    }
    // log:
    Animal::speak()
    Cat::speak()
    

    虚析构函数

    • 含有虚函数的类,应该将析构函数声明为虚函数(虚析构函数)
    • delete父类指针时,才会调用子类的析构函数,保证析构的完整性
    class Animal {
    public:
        virtual void speak(){
            cout << "Animal::speak()" << endl;
        }
        virtual ~Animal(){
            cout << "Animal::~Animal()" << endl;
        }
    };
    
    class Cat: public Animal {
    public:
         void speak(){
            Animal::speak();
            cout << "Cat::speak()" << endl;
        }
        
        ~Cat(){
            cout << "Animal::~Cat()" << endl;
        }
    };
    
    int main() {
        Animal *cat = new Cat();
        cat->speak();
        
        return 0;
    }
    
    // log:
    Animal::speak()
    Cat::speak()
    
    Q:为啥不析构
    

    相关文章

      网友评论

          本文标题:多态、虚函数、虚函数表

          本文链接:https://www.haomeiwen.com/subject/qujxmctx.html