• C 实现 C++继承多态 实例


    引述自:http://www.eventhelix.com/realtimemantra/basics/ComparingCPPAndCPerformance2.htm#.UaG1Kdd3-fg

    1
    // A typical example of inheritance and virtual function use. 2 // We would be mapping this code to equivalent C. 3 4 // Prototype graphics library function to draw a circle 5 void glib_draw_circle (int x, int y, int radius); 6 7 // Shape base class declaration 8 class Shape 9 { 10 protected: 11 int m_x; // X coordinate 12 int m_y; // Y coordinate 13 14 public: 15 // Pure virtual function for drawing 16 virtual void Draw() = 0; 17 18 // A regular virtual function 19 virtual void MoveTo(int newX, int newY); 20 21 // Regular method, not overridable. 22 void Erase(); 23 24 // Constructor for Shape 25 Shape(int x, int y); 26 27 // Virtual destructor for Shape 28 virtual ~Shape(); 29 }; 30 31 // Circle class declaration 32 class Circle : public Shape 33 { 34 private: 35 int m_radius; // Radius of the circle 36 37 public: 38 // Override to draw a circle 39 virtual void Draw(); 40 41 // Constructor for Circle 42 Circle(int x, int y, int radius); 43 44 // Destructor for Circle 45 virtual ~Circle(); 46 }; 47 48 // Shape constructor implementation 49 Shape::Shape(int x, int y) 50 { 51 m_x = x; 52 m_y = y; 53 } 54 55 // Shape destructor implementation 56 Shape::~Shape() 57 { 58 //... 59 } 60 61 // Circle constructor implementation 62 Circle::Circle(int x, int y, int radius) : Shape (x, y) 63 { 64 m_radius = radius; 65 } 66 67 // Circle destructor implementation 68 Circle::~Circle() 69 { 70 //... 71 } 72 73 // Circle override of the pure virtual Draw method. 74 void Circle::Draw() 75 { 76 glib_draw_circle(m_x, m_y, m_radius); 77 } 78 79 main() 80 { 81 // Define a circle with a center at (50,100) and a radius of 25 82 Shape *pShape = new Circle(50, 100, 25); 83 84 // Define a circle with a center at (5,5) and a radius of 2 85 Circle aCircle(5,5, 2); 86 87 // Various operations on a Circle via a Shape pointer 88 pShape->Draw(); 89 pShape->MoveTo(100, 100); 90 pShape->Erase(); 91 delete pShape; 92 93 // Invoking the Draw method directly 94 aCircle.Draw(); 95 }
      1     /*
      2     The following code maps the C++ code for the Shape and Circle classes
      3     to C code.
      4     */
      5      
      6     #include <stdio.h>
      7     #include <stdlib.h>
      8     #define TRUE 1
      9     #define FALSE 0
     10     typedef int BOOLEAN;
     11      
     12     /*
     13     Error handler used to stuff dummy VTable
     14     entries. This is covered later.
     15     */
     16     void pure_virtual_called_error_handler();
     17      
     18     /* Prototype graphics library function to draw a circle */
     19     void glib_draw_circle (int x, int y, int radius);
     20      
     21     typedef void (*VirtualFunctionPointer)(...);
     22      
     23     /*
     24     VTable structure used by the compiler to keep
     25     track of the virtual functions associated with a class.
     26     There is one instance of a VTable for every class
     27     containing virtual functions. All instances of
     28     a given class point to the same VTable.
     29     */
     30     struct VTable
     31     {
     32        /*
     33        d and i fields are used when multiple inheritance and virtual
     34        base classes are involved. We will be ignoring them for this
     35        discussion.
     36        */
     37        int d;
     38        int i;
     39      
     40        /*
     41        A function pointer to the virtual function to be called is
     42        stored here.
     43        */
     44        VirtualFunctionPointer pFunc;
     45     };
     46      
     47     /*
     48     The Shape class maps into the Shape structure in C. All
     49     the member variables present in the class are included
     50     as structure elements. Since Shape contains a virtual
     51     function, a pointer to the VTable has also been added.
     52     */
     53      
     54     struct Shape
     55     {
     56       int m_x;
     57       int m_y;
     58      
     59       /*
     60       The C++ compiler inserts an extra pointer to a vtable which
     61       will keep a function pointer to the virtual function that
     62       should be called.
     63       */
     64       VTable *pVTable;
     65     };
     66      
     67     /*
     68     Function prototypes that correspond to the C++ methods
     69     for the Shape class,
     70     */
     71     Shape *Shape_Constructor(Shape *this_ptr, int x, int y);
     72     void Shape_Destructor(Shape *this_ptr, bool dynamic);
     73     void Shape_MoveTo(Shape *this_ptr, int newX, int newY);
     74     void Shape_Erase(Shape *this_ptr);
     75      
     76     /*
     77     The Shape vtable array contains entries for Draw and MoveTo
     78     virtual functions. Notice that there is no entry for Erase,
     79     as it is not virtual. Also, the first two fields for every
     80     vtable entry are zero, these fields might have non zero
     81     values with multiple inheritance, virtual base classes
     82     A third entry has also been defined for the virtual destructor
     83     */
     84      
     85     VTable VTableArrayForShape[] =
     86     {
     87         /*
     88         Vtable entry virtual function Draw.
     89         Since Draw is pure virtual, this entry
     90         should never be invoked, so call error handler
     91         */
     92         { 0, 0, (VirtualFunctionPointer) pure_virtual_called_error_handler },
     93      
     94         /*
     95         This vtable entry invokes the base class's
     96         MoveTo method.
     97         */
     98         { 0, 0, (VirtualFunctionPointer) Shape_MoveTo },
     99      
    100         /* Entry for the virtual destructor */
    101         { 0, 0, (VirtualFunctionPointer) Shape_Destructor }
    102     };
    103      
    104     /*
    105     The struct Circle maps to the Circle class in the C++ code.
    106     The layout of the structure is:
    107     - Member variables inherited from the the base class Shape.
    108     - Vtable pointer for the class.
    109     - Member variables added by the inheriting class Circle.
    110     */
    111      
    112     struct Circle
    113     {
    114        /* Fields inherited from Shape */
    115        int m_x;
    116        int m_y;
    117        VTable *pVTable;
    118      
    119        /* Fields added by Circle */
    120        int m_radius;
    121     };
    122      
    123     /*
    124     Function prototypes for methods in the Circle class.
    125     */
    126      
    127     Circle *Circle_Constructor(Circle *this_ptr, int x, int y, int radius);
    128     void Circle_Draw(Circle *this_ptr);
    129     void Circle_Destructor(Circle *this_ptr, BOOLEAN dynamic);
    130      
    131     /* Vtable array for Circle */
    132      
    133     VTable VTableArrayForCircle[] =
    134     {
    135         /*
    136         Vtable entry virtual function Draw.
    137         Circle_Draw method will be invoked when Shape's
    138         Draw method is invoked
    139         */
    140         { 0, 0, (VirtualFunctionPointer) Circle_Draw },
    141      
    142         /*
    143         This vtable entry invokes the base class's
    144         MoveTo method.
    145         */
    146         { 0, 0, (VirtualFunctionPointer) Shape_MoveTo },
    147      
    148         /* Entry for the virtual destructor */
    149         { 0, 0, (VirtualFunctionPointer) Circle_Destructor }
    150     };
    151      
    152     Shape *Shape_Constructor(Shape *this_ptr, int x, int y)
    153     {
    154       /* Check if memory has been allocated for struct Shape. */
    155       if (this_ptr == NULL)
    156       {
    157         /* Allocate memory of size Shape. */
    158         this_ptr = (Shape *) malloc(sizeof(Shape));
    159       }
    160      
    161       /*
    162       Once the memory has been allocated for Shape,
    163       initialise members of Shape.
    164       */
    165       if (this_ptr)
    166       {  
    167         /* Initialize the VTable pointer to point to shape */
    168         this_ptr->pVTable = VTableArrayForShape;
    169         this_ptr->m_x = x;
    170         this_ptr->m_y = y;
    171       }
    172      
    173       return this_ptr;
    174     }
    175      
    176     void Shape_Destructor(Shape *this_ptr, BOOLEAN dynamic)
    177     {
    178       /*
    179       Restore the VTable to that for Shape. This is
    180       required so that the destructor does not invoke
    181       a virtual function defined by a inheriting class.
    182       (The base class destructor is invoked after inheriting
    183       class actions have been completed. Thus it is not
    184       safe to invoke the ineriting class methods from the
    185       base class destructor)
    186       */
    187       this_ptr->pVTable = VTableArrayForShape;
    188      
    189       /*...*/
    190      
    191       /*
    192       If the memory was dynamically allocated
    193       for Shape, explicitly free it.
    194       */
    195       if (dynamic)
    196       {
    197         free(this_ptr);
    198       }
    199     }
    200      
    201     Circle *Circle_Constructor(Circle *this_ptr, int x, int y, int radius)
    202     {
    203       /* Check if memory has been allocated for struct Circle. */
    204       if (this_ptr == NULL)
    205       {
    206         /* Allocate memory of size Circle. */
    207         this_ptr = (Circle *) malloc(sizeof(Circle));
    208       }
    209      
    210       /*
    211       Once the memory has been allocated for Circle,
    212       initialise members of Circle.
    213       */
    214       if (this_ptr)
    215       {
    216           /* Invoking the base class constructor */
    217           Shape_Constructor((Shape *)this_ptr, x, y);
    218           this_ptr->pVTable = VTableArrayForCircle;
    219      
    220           this_ptr->m_radius = radius;
    221       }
    222       return this_ptr;
    223     }
    224      
    225     void Circle_Destructor(Circle *this_ptr, BOOLEAN dynamic)
    226     {
    227       /* Restore the VTable to that for Circle */
    228       this_ptr->pVTable = VTableArrayForCircle;
    229      
    230       /*...*/
    231      
    232       /*
    233       Invoke the base class destructor after ineriting class
    234       destructor actions have been completed. Also note that
    235       that the dynamic flag is set to false so that the shape
    236       destructor does not free any memory.
    237       */
    238       Shape_Destructor((Shape *) this_ptr, FALSE);
    239      
    240       /*
    241       If the memory was dynamically allocated
    242       for Circle, explicitly free it.
    243       */
    244       if (dynamic)
    245       {
    246         free(this_ptr);
    247       }
    248     }
    249      
    250     void Circle_Draw(Circle *this_ptr)
    251     {
    252        glib_draw_circle(this_ptr->m_x, this_ptr->m_y, this_ptr->m_radius);
    253     }
    254      
    255     main()
    256     {  
    257       /*
    258       Dynamically allocate memory by passing NULL in this arguement.
    259       Also initialse members of struct pointed to by pShape.
    260       */
    261       Shape *pShape = (Shape *) Circle_Constructor(NULL, 50, 100, 25);
    262      
    263       /* Define a local variable aCircle of type struct Circle. */
    264       Circle aCircle;
    265      
    266       /* Initialise members of struct variable aCircle. */
    267       Circle_Constructor(&aCircle, 5, 5, 2);
    268      
    269       /*
    270       Virtual function Draw is called for the shape pointer. The compiler
    271       has allocated 0 offset array entry to the Draw virtual function.
    272       This code corresponds to "pShape->Draw();"
    273       */
    274       (pShape->pVTable[0].pFunc)(pShape);
    275      
    276       /*
    277       Virtual function MoveTo is called for the shape pointer. The compiler
    278       has allocared 1 offset array entry to the MoveTo virtual function.
    279       This code corresponds to "pShape->MoveTo(100, 100);"
    280       */
    281       (pShape->pVTable[1].pFunc)(pShape, 100, 100);
    282      
    283       /*
    284       The following code represents the Erase method. This method is
    285       not virtual and it is only defined in the base class. Thus
    286       the Shape_Erase C function is called.
    287       */
    288       Shape_Erase(pShape);
    289      
    290       /* Delete memory pointed to by pShape (explicit delete in original code).
    291       Since the destructor is declared virtual, the compiler has allocated
    292       2 offset entry to the virtual destructor
    293       This code corresponds to "delete pShape;".
    294       */
    295       (pShape->pVTable[2].pFunc)(pShape, TRUE);
    296      
    297       /*
    298       The following code corresponds to aCircle.Draw().
    299       Here the compiler can invoke the method directly instead of
    300       going through the vtable, since the type of aCircle is fully
    301       known. (This is very much compiler dependent. Dumb compilers will
    302       still invoke the method through the vtable).
    303       */
    304       Circle_Draw(&aCircle);
    305      
    306       /*
    307       Since memory was allocated from the stack for local struct
    308       variable aCircle, it will be deallocated when aCircle goes out of scope.
    309       The destructor will also be invoked. Notice that dynamic flag is set to
    310       false so that the destructor does not try to free memory. Again, the
    311       compiler does not need to go through the vtable to invoke the destructor.
    312       */
    313       Circle_Destructor(&aCircle, FALSE);
    314     }   
  • 相关阅读:
    红黑树以及与AVL树的区别
    yum安装mysql
    sql注入攻击
    http keep-alive
    csrf和xss
    点击事件跳转QQ 添加好友
    引入百度地图及出现的问题
    node 出现npm ERR! code ERR_TLS_CERT_ALTNAME_INVALID npm ERR! errno ERR_TLS_CERT_ALTNAME_INVALID npm ERR! request to https://registry.cnpmjs.org/vue-cli failed, reason:
    正则表达式校验-大于0的所有数,小数点后保留两位小数和正整数
    vue项目引入富文本编辑器(回显)
  • 原文地址:https://www.cnblogs.com/openix/p/3100045.html
Copyright © 2020-2023  润新知