实验六 多态性与虚函数

  • Post author:
  • Post category:其他



一、实验目的和要求




了解静态联编的动态联编的概念。掌握动态联编的条件。




二、实验内容


1.分析并调试下列程序。



  1. //sy6_1.cpp





  2. #include<iostream>





  3. using




    namespace


    std;



  4. class


    Base


  5. {


  6. public


    :



  7. virtual




    void


    f(


    float


    x){cout<<


    “Base::f(float)”


    <<x<<endl;}



  8. void


    g(


    float


    x){cout<<


    “Base::g(float)”


    <<x<<endl;}



  9. void


    h(


    float


    x){cout<<


    “Base::h(float)”


    <<x<<endl;}


  10. };


  11. class


    Derived:


    public


    Base


  12. {


  13. public


    :



  14. virtual




    void


    f(


    float


    x){cout<<


    “Derived::f(float}”


    <<x<<endl;}



  15. void


    g(


    int


    x){cout<<


    “Derived::g(int)”


    <<x<<endl;}



  16. void


    h(


    float


    x){cout<<


    “Derived::h(float)”


    <<x<<endl;}


  17. };


  18. int


    main()


  19. {

  20. Derived d;

  21. Base *pb=&d;

  22. Derived *pd=&d;

  23. pb->f(3.14f);

  24. pd->f(3.14f);

  25. pb->g(3.14f);

  26. pb->h(3.14f);

  27. pd->h(3.14f);


  28. return


    0;


  29. }


(1)找出以上程序中使用了重载和覆盖函数。


(2)写出程序的输出结果,并解释输出结果。

程序运行结果如下:

解释输出结果:

pb和pd指向同一地址,它们运行结果应该是相同的,但实际运行出来的结果却不相同,原因是决定pb和pd调用函数运行结果的不是他们指向的地址,而是他们的指针类型。“只有在通过基类指针或引用间接指向派生类子类型时多态性才会起作用”。在程序中pb是基类指针,pd是派生类指针,pd的所有函数调用都只是调用自己的函数,和多态性无关,所以pd的所有函数调用的结果都输出Derived::是完全正常的;pb的函数调用如果有virtual则根据多态性调用派生类的,如果没有virtual则是正常的静态函数调用,还是调用基类的,所以有virtual的f函数调用输出Derived::,其它两个没有virtual则还是输出Base::。

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. //sy6_3.cpp





  2. #include<iostream>





  3. using




    namespace


    std;



  4. class


    Point


  5. {


  6. public


    :


  7. Point(

    double


    i,


    double


    j){x=i;y=j;}



  8. double


    Area(){



    return


    0.0;}



  9. private


    :



  10. double


    x,y;


  11. };


  12. class


    Rectangle:


    public


    Point


  13. {


  14. public


    :


  15. Rectangle(

    double


    i,


    double


    j,


    double


    k,


    double


    l):Point(i,j){w=k;h=l;}



  16. double


    Area(){



    return


    w*h;}



  17. private


    :



  18. double


    w,h;


  19. };


  20. int


    main()


  21. {

  22. Point p(3.5,7);


  23. double


    A=p.Area();


  24. cout<<

    “Area= ”


    <<A<<endl;


  25. Rectangle r(1.2,3,5,7.8);

  26. A=r.Area();

  27. cout<<

    “Area= ”


    <<A<<endl;



  28. return


    0;


  29. }

写出程序的输出结果,并解释输出结果。

输出结果如下:


4. 分析并调试下列程序。



  1. //sy6_4.cpp





  2. #include<iostream>





  3. using




    namespace


    std;



  4. const




    double


    PI=3.1415;



  5. class


    Shap


  6. {


  7. public


    :



  8. virtual




    double


    Area()=0;


  9. };


  10. class


    Triangle:


    public


    Shap


  11. {


  12. public


    :


  13. Triangle(

    double


    h,


    double


    w){H=h;W=w;}



  14. double


    Area(){



    return


    0.5*H*W;}



  15. private


    :



  16. double


    H,W;


  17. };


  18. class


    Rectangle:


    public


    Shap


  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)

编写程序如下:



  1. //sy6_5.cpp





  2. #include <iostream>





  3. using




    namespace


    std;



  4. class


    Teacher


  5. {


  6. public


    :



  7. virtual




    int


    Salary()=0;



  8. virtual




    void


    Print(


    int


    )=0;


  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. class


    AssociateProfessor:


    public


    Teacher


  33. {


  34. private


    :



  35. char


    name[128];



  36. int


    lessons;



  37. public


    :


  38. AssociateProfessor()

  39. {

  40. cout<<

    “请输入姓名:”


    ;


  41. cin>>name;

  42. cout<<

    “请输入课时:”


    ;


  43. cin>>lessons;

  44. };


  45. int


    Salary()


  46. {


  47. return


    (3000+lessons*30);


  48. };


  49. void


    Print(


    int


    money)


  50. {

  51. cout<<

    “职称:副教授 姓名:”


    <<name<<


    ” 薪水:”


    <<money<<endl<<endl;


  52. };

  53. };



  54. class


    Lecturer:


    public


    Teacher


  55. {


  56. private


    :



  57. char


    name[128];



  58. int


    lessons;



  59. public


    :


  60. Lecturer()

  61. {

  62. cout<<

    “请输入姓名:”


    ;


  63. cin>>name;

  64. cout<<

    “请输入课时:”


    ;


  65. cin>>lessons;

  66. };


  67. int


    Salary()


  68. {


  69. return


    (2000+lessons*20);


  70. };


  71. void


    Print(


    int


    money)


  72. {

  73. cout<<

    “职称:讲师 姓名:”


    <<name<<


    “薪水:”


    <<money<<endl<<endl;


  74. };

  75. };



  76. int


    main()


  77. {

  78. Teacher *t = NULL;



  79. int


    money=0;



  80. //教授




  81. t =

    new


    Professor();


  82. money = t->Salary();

  83. t->Print(money);


  84. delete


    t;




  85. //副教授




  86. t =

    new


    AssociateProfessor();


  87. money = t->Salary();

  88. t->Print(money);


  89. delete


    t;




  90. //讲师




  91. t =

    new


    Lecturer();


  92. money = t->Salary();

  93. t->Print(money);


  94. delete


    t;


  95. t = NULL;


  96. return


    0;


  97. }

程序运行结果如下:


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


三、分析与讨论

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



版权声明:本文为qq_41798905原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。