实验6 多态性与虚函数

实验目的和要求

     了解静态联编的动态联编的概念。掌握动态联编的条件。
实验内容
1.分析并调试下列程序。
  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. 分析并调试下列程序
  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. }
(1)找出以上程序中使用了重载和覆盖函数。
(2)写出程序的输出结果,并解释输出结果。
运行结果如下:

3. 分析并调试下列程序
程序如下:
  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. 分析并调试下列程序
程序如下:
  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. public:;
  20. Rectangle( double h, double w){H=h;W=w;}
  21. double Area(){ return H*W;}
  22. private:
  23. double H,W;
  24. };
  25. class Circle: public Shap
  26. {
  27. public:
  28. Circle( double r){R=r;}
  29. double Area(){ return PI*R*R;}
  30. private:
  31. double R;
  32. };
  33. class Square: public Shap
  34. {
  35. public:
  36. Square( double s){S=s;}
  37. double Area(){ return S*S;}
  38. private:
  39. double S;
  40. };
  41. double Total(Shap *s[],int n)
  42. {
  43. double sum= 0;
  44. for( int i= 0;i<n;i++)
  45. sum+=s[i]->Area();
  46. return sum;
  47. }
  48. int main()
  49. {
  50. Shap *s[ 5];
  51. s[ 0]= new Square( 8.0);
  52. s[ 1]= new Rectangle( 3.0, 8.0);
  53. s[ 2]= new Square( 12.0);
  54. s[ 3]= new Circle( 8.0);
  55. s[ 4]= new Triangle( 5.0, 4.0);
  56. double sum=Total(s, 5);
  57. cout<< "SUM = "<<sum<< endl;
  58. return 0;
  59. }

运行结果如下:

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

5. 某学校对教师每个月工资的计算规定如下:固定工资+课时补贴;教授的固定工资为5000元,每个课时补贴50;副教授的固定工资为3000,每个课时补贴30元;讲师的固定工资为2000元,每个课时补贴20元。定义教师抽象类,派生不同职称的教师类,编写程序求若干个教师的月工资。(sy6_5.cpp)
  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. class Professor: public Teacher
  10. {
  11. private:
  12. char name[ 128];
  13. int lessons;
  14. public:
  15. Professor()
  16. {
  17. cout<< "请输入姓名:";
  18. cin>>name; //字符串中不能有空格
  19. cout<< "请输入课时:";
  20. cin>>lessons; //必须输入数字
  21. };
  22. int Salary()
  23. {
  24. return ( 5000+lessons* 50);
  25. };
  26. void Print(int money)
  27. {
  28. cout<< "职称:教授 姓名:"<<name<< " 薪水:"<<money<< endl<< endl;
  29. };
  30. };
  31. class AssociateProfessor: public Teacher
  32. {
  33. private:
  34. char name[ 128];
  35. int lessons;
  36. public:
  37. AssociateProfessor()
  38. {
  39. cout<< "请输入姓名:";
  40. cin>>name;
  41. cout<< "请输入课时:";
  42. cin>>lessons;
  43. };
  44. int Salary()
  45. {
  46. return ( 3000+lessons* 30);
  47. };
  48. void Print(int money)
  49. {
  50. cout<< "职称:副教授 姓名:"<<name<< " 薪水:"<<money<< endl<< endl;
  51. };
  52. };
  53. class Lecturer: public Teacher
  54. {
  55. private:
  56. char name[ 128];
  57. int lessons;
  58. public:
  59. Lecturer()
  60. {
  61. cout<< "请输入姓名:";
  62. cin>>name;
  63. cout<< "请输入课时:";
  64. cin>>lessons;
  65. };
  66. int Salary()
  67. {
  68. return ( 2000+lessons* 20);
  69. };
  70. void Print(int money)
  71. {
  72. cout<< "职称:讲师 姓名:"<<name<< "薪水:"<<money<< endl<< endl;
  73. };
  74. };
  75. int main()
  76. {
  77. Teacher *t = NULL;
  78. int money= 0;
  79. //教授
  80. t = new Professor();
  81. money = t->Salary();
  82. t->Print(money);
  83. delete t;
  84. //副教授
  85. t = new AssociateProfessor();
  86. money = t->Salary();
  87. t->Print(money);
  88. delete t;
  89. //讲师
  90. t = new Lecturer();
  91. money = t->Salary();
  92. t->Print(money);
  93. delete t;
  94. t = NULL;
  95. return 0;
  96. }




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

分析与讨论

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

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值