第18课 - 多态与继承 - 下

匿名 (未验证) 提交于 2019-12-03 00:22:01

第18课 - 多态与继承 - 下

 Source Example 1:             #include <iostream>              /* run this program using the console pauser or add your own getch, system("pause") or input loop */              class Parent {             public:                 virtual void func()                 {                     printf("Parent->");                     printf("func()!\n");                 }                                  virtual void func(int i)                 {                     printf("Parent->");                     printf("func(int i)!\n");                 }                                  virtual void func(int i, int j)                 {                     printf("Parent->");                     printf("func(int i, int j)!\n");                 }             };              class Child : public Parent             {             public:                 virtual void func(int i)                 {                     printf("Child->");                     printf("func(int i)!\n");                 }                                  virtual void func(int i, int j)                 {                     printf("Child->");                     printf("func(int i, int j)!\n");                 }                                  void func(int i, int j, int k)                 {                     printf("Child->");                     printf("func(int i, int j, int k)!\n");                 }             };              void run(Parent* p)             {                 p->func(1,2);             }              int main(int argc, char** argv) {                                  Parent p;                 Child c;                                  p.func();                 p.func(1);                 p.func(1,2);                                  /* 编译报错,因为void func(int i, int j, int k)函数将继承的func函数名称覆盖了 */                 /* 并没有发生函数重载,函数重载发生在同一作用域之间 */                 //c.func();                                  /* 这样才能调用父类中的func函数 */                 c.Parent::func();                                  /* Child里面定义的两个func函数处于同一作用域,可以发生重载 */                 c.func(1,2);                                  printf("\n");                 /* 会发生多态 */                 run(&p);                 run(&c);                                                       return 0;             }



1.1 重载与重写区别









通过虚函数表指针VPTR调用重写函数是在程序运行时进行的,因此需要寻址操作才能真正的确定应该调用的函数。



结论:构造函数中调用虚函数无法实现多态。


 Source Example2.2(构造函数中的"多态")                 #include <iostream>                  /* run this program using the console pauser or add your own getch, system("pause") or input loop */                  class Parent {                 public:                     Parent()                     {                         this->func();                     }                     virtual void func()                     {                         printf("Parent->");                         printf("func()!\n");                     }                 };                  class Child : public Parent                 {                 public:                     virtual void func(int i)                     {                         printf("Child->");                         printf("func(int i)!\n");                     }                 };                                   int main(int argc, char** argv) {                                          /* 会调用父类的func函数 */                     Parent p;                     /*                        * 1. 首先会执行父类函数的构造函数,此时VPTR指针指向父类的虚函数表                      * 2. 调用虚函数表的func函数,即父类中的func函数                      * 3. 其次会执行子类函数的构造函数,此时VPTR指针指向子类的虚函数表                      * 4. 因此会调用父类的func函数,多态并没有发生                      * 5. 结论,构造函数中无法实现多态                      */                     Child c;                                                      return 0;                 }                 




在进行面向对象分析时,会有一些抽象的概念


在现实中需要知道图像的具体类型才能球面积,所以对概念上的"图形"求面积是没有意义的!

3.2 用Shape作为基类进行继承

Source Example 3.2:              #include <iostream>              /* run this program using the console pauser or add your own getch, system("pause") or input loop */              class Shape{             public:                 virtual double area()                 {                     return 0;                 }             };              class Rectangle : public Shape{             protected:                 int a;                 int b;             public:                 Rectangle(int a, int b)                 {                     this->a = a;                     this->b = b;                 }                 virtual double area()                 {                     return a * b;                 }             };              class Circle : public Shape{             protected:                 int r;             public:                 Circle(int r)                 {                     this->r = r;                 }                 virtual double area()                 {                     return 3.14 * r * r;                 }             };              void area(Shape* s)             {                 printf("area = %lf\n", s->area());             }                          int main(int argc, char** argv) {                                  Rectangle r(1,2);                 Circle c(3);                 Shape s;                                  area(&r);                 area(&c);                 area(&s);                                              return 0;             }







Source Example3.4:         #include <iostream>          /* run this program using the console pauser or add your own getch, system("pause") or input loop */          class Shape{         public:             virtual double area() = 0;         };          class Rectangle : public Shape{         protected:             int a;             int b;         public:             Rectangle(int a, int b)             {                 this->a = a;                 this->b = b;             }             /* 子类中必须要有重写Shape类中的area函数,不然会报错 */             virtual double area()             {                 return a * b;             }         };          class Circle : public Shape{         protected:             int r;         public:             Circle(int r)             {                 this->r = r;             }             /* 子类中必须要有重写Shape类中的area函数,不然会报错 */             virtual double area()             {                 return 3.14 * r * r;             }         };          void area(Shape* s)         {             printf("area = %lf\n", s->area());         }                  int main(int argc, char** argv) {                          Rectangle r(1,2);             Circle c(3);             /* 编译会报错,因为不能定义抽象类的对象 */             Shape s;                          area(&r);             area(&c);                                      return 0;         }

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!