zoukankan      html  css  js  c++  java
  • C++虚函数与多态

    多态性是面向对象程序设计的关键技术之一。利用多态性技术,可以调用同一个函数名的函数,实现完全不同的功能。若程序设计语言不支持多态性,不能称为面向对象的语言。

    在C++中有两种多态性:

    • 编译时的多态性:通过函数的重载和运算符的重载来实现的。
    • 运行时的多态性:在程序执行前,无法根据函数名和参数来确定该调用哪一个函数,必须在程序执行过程中,根据具体情况来动态地确定。它是通过类继承关系和虚函数来实现的。

    运行时的多态示例代码如下:

    #include <iostream>
    using namespace std;
    class Animal
    {
    public:
          virtual void display() { cout << "I am a animal" << endl; }
    };
    class Duck : public Animal
    {
    public:    
         void display() { cout << "I am a duck" << endl; }
    };
    class Tiger : public Animal
    {
    public:
         void display() { cout << "I am a tiger" << endl; }
    };
    
    int main(int argc, char* argv[])
    {
        Animal *animal = new Animal();
        Animal *duck = new Duck();;
        Animal *tiger = new Tiger();
        
        animal->display();    
        duck->display();
        tiger->display();
        
        getchar();
        delete animal;
        delete duck;
        delete tiger;
        return 0;
    }
          运行结果如下:

     原理

    为了达到动态绑定(后期绑定)的目的,C++ 编译器透过虚拟函数表(常被称为vtable)。每一个「内含虚拟函数的类别」,编译器都会为它做出一个虚拟函数表,中的每一笔元素都指向一个虚拟函数的地址。此外,编译器当然也会为类别加上一项成员变量,是一个指向该虚拟函数表的指针(常被称为vptr)。

          如下图所示:

    明白了虚函数的工作原理,我突然想到关于非虚函数的问题。为什么指向子类的父类指针在调用非虚函数时,调用的全是父类的方法?

    我查阅了《c++ Primer》,书中这样说:

    因为可以使用基类类型的指针或引用来引用派生类型对象,所以,使用基类
    类型的引用或指针时,不知道指针或引用所绑定的对象的类型:基类类型的引用
    或指针可以引用基类类型对象,也可以引用派生类型对象。无论实际对象具有哪
    种类型,编译器都将它当作基类类型对象。将派生类对象当作基类对象是安全的,
    因为每个派生类对象都拥有基类子对象。而且,派生类继承基类的操作,即,任
    何可以在基类对象上执行的操作也可以通过派生类对象使用。

  • 相关阅读:
    20162302
    20162302
    20162302 实验三《敏捷开发与XP实践》实验报告
    20162302 第九周作业
    20162302 第八周作业
    20162302 实验二《面向对象程序设计》实验报告
    20162302 第七周作业
    项目Alpha冲刺Day8
    项目Alpha冲刺Day7
    项目Alpha冲刺Day5
  • 原文地址:https://www.cnblogs.com/wangke1020/p/3654773.html
Copyright © 2011-2022 走看看