第六章:多态性与虚函数

一:实验目的和要求

了解静态联编的动态联编的概念。掌握动态联编的条件。
实验内容
1.分析并调试下列程序。

[html]  view plain  copy
  1. #include<iostream>   
  2. using namespace std;   
  3. class Base   
  4. {   
  5.     public:   
  6.         virtual void f(float x){cout<<"Base::f(float)"<<x<<endl;}   
  7.         void g(float x){cout<<"Base::g(float)"<<x<<endl;}   
  8.         void h(float x){cout<<"Base::h(float)"<<x<<endl;}   
  9. };   
  10. class Derived:public Base   
  11. {   
  12.    public:   
  13.         virtual void f(float x){cout<<"Derived::f(float}"<<x<<endl;}   
  14.         void g(int x){cout<<"Derived::g(int)"<<x<<endl;}   
  15.         void h(float x){cout<<"Derived::h(float)"<<x<<endl;}   
  16. };   
  17. int main()   
  18. {   
  19.     Derived d;   
  20.     Base *pb=&d;   
  21.     Derived *pd=&d;   
  22.     pb->f(3.14f);   
  23.     pd->f(3.14f);   
  24.     pb->g(3.14f);   
  25.     pb->h(3.14f);   
  26.     pd->h(3.14f);   
  27.     return 0;   
  28. }   
[html]  view plain  copy
  1. #include<iostream>    
  2. using namespace std;    
  3. class Base    
  4. {    
  5.     public:    
  6.         virtual void f(float x){cout<<"Base::f(float)"<<x<<endl;}    
  7.         void g(float x){cout<<"Base::g(float)"<<x<<endl;}    
  8.         void h(float x){cout<<"Base::h(float)"<<x<<endl;}    
  9. };    
  10. class Derived:public Base    
  11. {    
  12.    public:    
  13.         virtual void f(float x){cout<<"Derived::f(float}"<<x<<endl;}    
  14.         void g(int x){cout<<"Derived::g(int)"<<x<<endl;}    
  15.         void h(float x){cout<<"Derived::h(float)"<<x<<endl;}    
  16. };    
  17. int main()    
  18. {    
  19.     Derived d;    
  20.     Base *pb=&d;    
  21.     Derived *pd=&d;    
  22.     pb->f(3.14f);    
  23.     pd->f(3.14f);    
  24.     pb->g(3.14f);    
  25.     pb->h(3.14f);    
  26.     pd->h(3.14f);    
  27.     return 0;    
  28. }    
(1)找出以上程序中使用了重载和覆盖函数。
(2)写出程序的输出结果,并解释输出结果
程序的输出结果如下:

分析:
在程序中pb是基类指针,pd是派生类指针,pd的所有函数调用都只是调用自己的函数

2. 分析并调试下列程序

[html]  view plain  copy
  1. #include<iostream>     
  2. using namespace std;     
  3. class Base     
  4. {     
  5.     public:     
  6.         void f(int x){cout<<"Base::f(int)"<<x<<endl;}     
  7.         void f(float x){cout<<"Base::f(float)"<<x<<endl;}     
  8.        virtual void g(void){cout<<"Base::g(void)"<<endl;}     
  9. };     
  10. class Derived:public Base     
  11. {     
  12.     public:     
  13.         virtual void g(void){cout<<"Derived::g(void}"<<endl;}     
  14. };     
  15. int main()     
  16. {     
  17.     Derived d;     
  18.    Base *pb=&d;     
  19.     pb->f(42);     
  20.     pb->f(3.14f);     
  21.     pb->g();     
  22.     return 0;     
  23. }   
[html]  view plain  copy
  1. #include<iostream>      
  2. using namespace std;      
  3. class Base      
  4. {      
  5.     public:      
  6.         void f(int x){cout<<"Base::f(int)"<<x<<endl;}      
  7.         void f(float x){cout<<"Base::f(float)"<<x<<endl;}      
  8.        virtual void g(void){cout<<"Base::g(void)"<<endl;}      
  9. };      
  10. class Derived:public Base      
  11. {      
  12.     public:      
  13.         virtual void g(void){cout<<"Derived::g(void}"<<endl;}      
  14. };      
  15. int main()      
  16. {      
  17.     Derived d;      
  18.    Base *pb=&d;      
  19.     pb->f(42);      
  20.     pb->f(3.14f);      
  21.     pb->g();      
  22.     return 0;      
  23. }    

3. 分析并调试下列程序
程序如下:

[html]  view plain  copy
  1. #include<iostream>     
  2. using namespace std;     
  3. class Point     
  4. {     
  5.     public:     
  6.         Point(double i,double j){x=i;y=j;}     
  7.         double Area(){return 0.0;}     
  8.     private:     
  9.         double x,y;     
  10. };     
  11. class Rectangle:public Point     
  12. {     
  13.     public:     
  14.        Rectangle(double i,double j,double k,double l):Point(i,j){w=k;h=l;}     
  15.         double Area(){return w*h;}     
  16.     private:     
  17.         double w,h;     
  18. };     
  19. int main()     
  20. {     
  21.     Point p(3.5,7);     
  22.     double A=p.Area();     
  23.     cout<<"Area= "<<A<<endl;     
  24.     Rectangle r(1.2,3,5,7.8);     
  25.     A=r.Area();     
  26.     cout<<"Area= "<<A<<endl;     
  27.    return 0;     
  28. }   
[html]  view plain  copy
  1. #include<iostream>      
  2. using namespace std;      
  3. class Point      
  4. {      
  5.     public:      
  6.         Point(double i,double j){x=i;y=j;}      
  7.         double Area(){return 0.0;}      
  8.     private:      
  9.         double x,y;      
  10. };      
  11. class Rectangle:public Point      
  12. {      
  13.     public:      
  14.        Rectangle(double i,double j,double k,double l):Point(i,j){w=k;h=l;}      
  15.         double Area(){return w*h;}      
  16.     private:      
  17.         double w,h;      
  18. };      
  19. int main()      
  20. {      
  21.     Point p(3.5,7);      
  22.     double A=p.Area();      
  23.     cout<<"Area= "<<A<<endl;      
  24.     Rectangle r(1.2,3,5,7.8);      
  25.     A=r.Area();      
  26.     cout<<"Area= "<<A<<endl;      
  27.    return 0;      
  28. }    
写出程序的输出结果,并解释输出结果
运行结果如下:

4. 分析并调试下列程序
程序如下:

[html]  view plain  copy
  1. #include<iostream>   
  2. using namespace std;   
  3. const double PI=3.1415;   
  4. class Shap   
  5. {   
  6.     public:   
  7.         virtual double Area()=0;   
  8. };   
  9. class Triangle:public Shap   
  10. {   
  11.     public:   
  12.         Triangle(double h,double w){H=h;W=w;}   
  13.        double Area(){return 0.5*H*W;}   
  14.     private:   
  15.         double H,W;   
  16. };   
  17. class Rectangle:public Shap   
  18. {   
  19.    
  20.     public:;   
  21.         Rectangle(double h,double w){H=h;W=w;}   
  22.        double Area(){return H*W;}   
  23.     private:   
  24.         double H,W;   
  25. };   
  26. class Circle:public Shap   
  27. {   
  28.     public:   
  29.         Circle(double r){R=r;}   
  30.         double Area(){return PI*R*R;}   
  31.     private:   
  32.         double R;   
  33. };   
  34. class Square:public Shap   
  35. {   
  36.     public:   
  37.        Square(double s){S=s;}   
  38.         double Area(){return S*S;}   
  39.     private:   
  40.         double S;   
  41. };   
  42. double Total(Shap *s[],int n)   
  43. {   
  44.     double sum=0;   
  45.     for(int i=0;i<n;i++)   
  46.         sum+=s[i]->Area();   
  47.     return sum;   
  48. }   
  49. int main()   
  50. {   
  51.    Shap *s[5];   
  52.    s[0]=new Square(8.0);   
  53.    s[1]=new Rectangle(3.0,8.0);   
  54.    s[2]=new Square(12.0);   
  55.    s[3]=new Circle(8.0);   
  56.    s[4]=new Triangle(5.0,4.0);   
  57.    double sum=Total(s,5);   
  58.    cout<<"SUM = "<<sum<<endl;   
  59.     return 0;   
  60. }   
[html]  view plain  copy
  1. #include<iostream>    
  2. using namespace std;    
  3. const double PI=3.1415;    
  4. class Shap    
  5. {    
  6.     public:    
  7.         virtual double Area()=0;    
  8. };    
  9. class Triangle:public Shap    
  10. {    
  11.     public:    
  12.         Triangle(double h,double w){H=h;W=w;}    
  13.        double Area(){return 0.5*H*W;}    
  14.     private:    
  15.         double H,W;    
  16. };    
  17. class Rectangle:public Shap    
  18. {    
  19.     
  20.     public:;    
  21.         Rectangle(double h,double w){H=h;W=w;}    
  22.        double Area(){return H*W;}    
  23.     private:    
  24.         double H,W;    
  25. };    
  26. class Circle:public Shap    
  27. {    
  28.     public:    
  29.         Circle(double r){R=r;}    
  30.         double Area(){return PI*R*R;}    
  31.     private:    
  32.         double R;    
  33. };    
  34. class Square:public Shap    
  35. {    
  36.     public:    
  37.        Square(double s){S=s;}    
  38.         double Area(){return S*S;}    
  39.     private:    
  40.         double S;    
  41. };    
  42. double Total(Shap *s[],int n)    
  43. {    
  44.     double sum=0;    
  45.     for(int i=0;i<n;i++)    
  46.         sum+=s[i]->Area();    
  47.     return sum;    
  48. }    
  49. int main()    
  50. {    
  51.    Shap *s[5];    
  52.    s[0]=new Square(8.0);    
  53.    s[1]=new Rectangle(3.0,8.0);    
  54.    s[2]=new Square(12.0);    
  55.    s[3]=new Circle(8.0);    
  56.    s[4]=new Triangle(5.0,4.0);    
  57.    double sum=Total(s,5);    
  58.    cout<<"SUM = "<<sum<<endl;    
  59.     return 0;    
  60. }    

运行结果如下:


(1)指出抽象类。
(2)指出纯虚函数,并说明它的作用。
(3)每个类的作用是什么?整个程序的作用是什么?

5. 某学校对教师每个月工资的计算规定如下:固定工资+课时补贴;教授的固定工资为5000元,每个课时补贴50;副教授的固定工资为3000,每个课时补贴30元;讲师的固定工资为2000元,每个课时补贴20元。定义教师抽象类,派生不同职称的教师类,编写程序求若干个教师的月工资。(sy6_5.cpp)

[html]  view plain  copy
  1. #include <iostream>     
  2. using namespace std;     
  3. class Teacher     
  4. {     
  5. public:     
  6.     virtual int Salary()=0;     
  7.     virtual void Print(int)=0;     
  8. };     
  9.      
  10. class Professor:public Teacher     
  11. {     
  12. private:     
  13.     char name[128];     
  14.     int lessons;     
  15. public:     
  16.     Professor()     
  17.     {     
  18.         cout<<"请输入姓名:";     
  19.         cin>>name;      //字符串中不能有空格     
  20.         cout<<"请输入课时:";     
  21.         cin>>lessons;   //必须输入数字     
  22.     };     
  23.     int Salary()     
  24.     {     
  25.         return (5000+lessons*50);     
  26.     };     
  27.     void Print(int money)     
  28.     {     
  29.         cout<<"职称:教授 姓名:"<<name<<" 薪水:"<<money<<endl<<endl;     
  30.     };     
  31. };     
  32.      
  33. class AssociateProfessor:public Teacher     
  34. {     
  35. private:     
  36.     char name[128];     
  37.     int lessons;     
  38. public:     
  39.     AssociateProfessor()     
  40.     {     
  41.         cout<<"请输入姓名:";     
  42.         cin>>name;     
  43.         cout<<"请输入课时:";     
  44.         cin>>lessons;     
  45.     };     
  46.     int Salary()     
  47.     {     
  48.         return (3000+lessons*30);     
  49.     };     
  50.     void Print(int money)     
  51.     {     
  52.         cout<<"职称:副教授 姓名:"<<name<<" 薪水:"<<money<<endl<<endl;     
  53.     };     
  54. };     
  55.      
  56. class Lecturer:public Teacher     
  57. {     
  58. private:     
  59.     char name[128];     
  60.     int lessons;     
  61. public:     
  62.     Lecturer()     
  63.     {     
  64.         cout<<"请输入姓名:";     
  65.         cin>>name;     
  66.         cout<<"请输入课时:";     
  67.         cin>>lessons;     
  68.     };     
  69.     int Salary()     
  70.     {     
  71.         return (2000+lessons*20);     
  72.     };     
  73.     void Print(int money)     
  74.     {     
  75.         cout<<"职称:讲师 姓名:"<<name<<"薪水:"<<money<<endl<<endl;     
  76.     };     
  77. };     
  78.      
  79. int main()     
  80. {     
  81.     Teacher *t = NULL;     
  82.      
  83.     int money=0;     
  84.     //教授     
  85.      t = new Professor();     
  86.     money = t->Salary();     
  87.     t->Print(money);     
  88.     delete t;     
  89.      
  90.     //副教授     
  91.     t = new AssociateProfessor();     
  92.     money = t->Salary();     
  93.     t->Print(money);     
  94.     delete t;     
  95.      
  96.     //讲师     
  97.     t = new Lecturer();     
  98.     money = t->Salary();     
  99.     t->Print(money);     
  100.     delete t;     
  101.     t = NULL;     
  102.     return 0;     
  103. }   
[html]  view plain  copy
  1. #include <iostream>      
  2. using namespace std;      
  3. class Teacher      
  4. {      
  5. public:      
  6.     virtual int Salary()=0;      
  7.     virtual void Print(int)=0;      
  8. };      
  9.       
  10. class Professor:public Teacher      
  11. {      
  12. private:      
  13.     char name[128];      
  14.     int lessons;      
  15. public:      
  16.     Professor()      
  17.     {      
  18.         cout<<"请输入姓名:";      
  19.         cin>>name;      //字符串中不能有空格      
  20.         cout<<"请输入课时:";      
  21.         cin>>lessons;   //必须输入数字      
  22.     };      
  23.     int Salary()      
  24.     {      
  25.         return (5000+lessons*50);      
  26.     };      
  27.     void Print(int money)      
  28.     {      
  29.         cout<<"职称:教授 姓名:"<<name<<" 薪水:"<<money<<endl<<endl;      
  30.     };      
  31. };      
  32.       
  33. class AssociateProfessor:public Teacher      
  34. {      
  35. private:      
  36.     char name[128];      
  37.     int lessons;      
  38. public:      
  39.     AssociateProfessor()      
  40.     {      
  41.         cout<<"请输入姓名:";      
  42.         cin>>name;      
  43.         cout<<"请输入课时:";      
  44.         cin>>lessons;      
  45.     };      
  46.     int Salary()      
  47.     {      
  48.         return (3000+lessons*30);      
  49.     };      
  50.     void Print(int money)      
  51.     {      
  52.         cout<<"职称:副教授 姓名:"<<name<<" 薪水:"<<money<<endl<<endl;      
  53.     };      
  54. };      
  55.       
  56. class Lecturer:public Teacher      
  57. {      
  58. private:      
  59.     char name[128];      
  60.     int lessons;      
  61. public:      
  62.     Lecturer()      
  63.     {      
  64.         cout<<"请输入姓名:";      
  65.         cin>>name;      
  66.         cout<<"请输入课时:";      
  67.         cin>>lessons;      
  68.     };      
  69.     int Salary()      
  70.     {      
  71.         return (2000+lessons*20);      
  72.     };      
  73.     void Print(int money)      
  74.     {      
  75.         cout<<"职称:讲师 姓名:"<<name<<"薪水:"<<money<<endl<<endl;      
  76.     };      
  77. };      
  78.       
  79. int main()      
  80. {      
  81.     Teacher *t = NULL;      
  82.       
  83.     int money=0;      
  84.     //教授      
  85.      t = new Professor();      
  86.     money = t->Salary();      
  87.     t->Print(money);      
  88.     delete t;      
  89.       
  90.     //副教授      
  91.     t = new AssociateProfessor();      
  92.     money = t->Salary();      
  93.     t->Print(money);      
  94.     delete t;      
  95.       
  96.     //讲师      
  97.     t = new Lecturer();      
  98.     money = t->Salary();      
  99.     t->Print(money);      
  100.     delete t;      
  101.     t = NULL;      
  102.     return 0;      
  103. }    

运行结果如下:


6. 把实验5中的第4题的Shape类定义为抽象类,提供共同操作界面的纯虚函数。TwoDimShape类和ThreeDimShape类仍然抽象类,第3层具体类才能提供全部函数的实现。在测试函数中,使用基类指针实现不同派生类对象的操作。

二:分析与讨论

1.结合实验内容中第1题和第2题,说明重载与覆盖的区别。

      答:重载与覆盖的区别:1、方法的覆盖是子类和父类之间的关系,是垂直关系;方法的重载是同一个类中方法之间的关系,是水平关系2、覆盖只能由一个方法,或只能由一对方法产生关系;方法的重载是多个方法之间的关系。3、覆盖要求参数列表相同;重载要求参数列表不同。4、覆盖关系中,调用那个方法体,是根据对象的类型(对象对应存储空间类型)来决定;重载关系,是根据调用时的实参表与形参表来选择方法体的。

2.总结静态联编和动态联编的区别和动态联编的条件。

     答:静态联编是指联编工作在编译阶段完成的,这种联编过程是在程序运行之前完成的,又称为早期联编。要实现静态联编,在编译阶段就必须确定程序中的操作调用(如函数调用)与执行该操作代码间的关系,确定这种关系称为束定,在编译时的束定称为静态束定。静态联编对函数的选择是基于指向对象的指针或者引用的类型。其优点是效率高,但灵活性差。

        动态联编是指联编在程序运行时动态地进行,根据当时的情况来确定调用哪个同名函数,实际上是在运行时虚函数的实现。这种联编又称为晚期联编,或动态束定。动态联编对成员函数的选择是基于对象的类型,针对不同的对象类型将做出不同的编译结果。C++中一般情况下的联编是静态联编,但是当涉及到多态性和虚函数时应该使用动态联编。动态联编的优点是灵活性强,但效率低。                                                                                                                                                                     动态联编的条件:
①必须把动态联编的行为定义为类的虚函数。                                                                                                                 
②类之间应满足子类型关系,通常表现为一个类从另一个类公有派生而来。                                                                         
③必须先使用基类指针指向子类型的对象,然后直接或者间接使用基类指针调用虚函数。

猜你喜欢

转载自blog.csdn.net/hjmhjm1314/article/details/80670523