C专家编程 第11章 你懂得C,所以C++不再话下 11.15 C++如何表现多态

发布于:2022-12-20 ⋅ 阅读:(279) ⋅ 点赞:(0)

    C++如何表现多态
    #include <stdio.h>
    class Fruit{
        public: virtual void peel() {
            printf("peeling a base class fruit\n");
        }
        slice();
        juice();
        private: int weight, calories_per_oz;
    }; 
    通过编译和执行,结果如下:
    peeling an apple
    多态是一种运行时效果。它是指C++对象运行时决定调用哪个函数来实现某个特定操作的过程。运行时系统查看虚函数的对象,并选择适合该类型对象的成员函数。如果它是一个派生类对象,我们就不希望它调用基类版本的成员函数,而是希望它调用派生类的成员函数。但是当基类被编译时,编译器可能看不到这种情况。因此,这个效果必须在运行时动态实现,用C++的术语就是“虚拟实现”。

    单继承通常通过在每个对象内包含一个vptr指针来实现虚拟函数。vptr指针指向一个叫作vtbl的函数指针向量(称为虚拟函数表,也称为V表)。每个类都有这样一个向量,类中的每个虚拟的函数在该向量中都有一条记录。使用这个方法,该类的所有对象可以共享实现代码。虚拟函数表的布局是预先设置好的,某个成员函数的函数指针在该类所有子类的虚拟函数表中的偏移地址都是一样的。在运行时,对虚拟成员函数的调用是通过vptr指针根据适当的偏移量调用虚拟函数表中合适的函数指针来实现的,它是一种间接调用。多重继承的情况更为复杂,另外需要一层的间接形式。如果你搞不明白,可以对它画一幅图,线的最末端就是需要调用的成员函数。

    /*
    ** operator overload.
    */
    #include <stdio.h>
    #include <stdlib.h>
    class Fruit {
        public:
            Fruit( int i, int j );
            virtual void peel( void );
            void slice( void );
            void juice( void );
            virtual ~Fruit( void );
        private: int weight, calories_per_oz;
    };
    
    class Apple : public Fruit{
        public:
            Apple( int i, int j );
            void peel( void );
            /*void make_candy_apple(float weight);*/
            ~Apple( void );
    };
    
    int main( void ){
        Fruit *fruit = new Apple( 1, 2 );
        fruit->Fruit::peel();
        fruit->peel();
        delete fruit;
    
        return EXIT_SUCCESS;
    }
    
    Fruit::Fruit( int i, int j ){
        printf( "fruit constructor is called!\n" );
        weight = i;
        this->calories_per_oz = j;
    }
    
    void Fruit::peel( void ){
        printf( "fruit peel!\n" );
    }
    
    void Fruit::slice( void ){
        printf( "in slice!\n" );
    }
    
    void Fruit::juice( void ){
        printf( "in juice!\n" );
    }
    
    Fruit::~Fruit( void ){
        printf( "fruit destructor is called!\n" );
    }
    
    Apple::Apple( int i, int j ) : Fruit( i, j ){
        printf( "apple constructor is called!\n" );
    }
    
    void Apple::peel( void ){
        printf( "apple peel!\n" );
    }
    
    Apple::~Apple( void ){
        printf( "apple destructor is called!\n" );
    }

输出:


网站公告

今日签到

点亮在社区的每一天
去签到