实验6

实验目的和要求

    了解静态联编的动态联编的概念。掌握动态联编的条件。
实验内容
1.分析并调试下列程序。
  1. <span style="font-family:SimSun;font-size:16px;">//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. }</span>  
//sy6_1.cpp
#include<iostream>
using namespace std;
class Base
{
    public:
        virtual void f(float x){cout<<"Base::f(float)"<<x<<endl;}
        void g(float x){cout<<"Base::g(float)"<<x<<endl;}
        void h(float x){cout<<"Base::h(float)"<<x<<endl;}
};
class Derived:public Base
{
    public:
        virtual void f(float x){cout<<"Derived::f(float}"<<x<<endl;}
        void g(int x){cout<<"Derived::g(int)"<<x<<endl;}
        void h(float x){cout<<"Derived::h(float)"<<x<<endl;}
};
int main()
{
    Derived d;
    Base *pb=&d;
    Derived *pd=&d;
    pb->f(3.14f);
    pd->f(3.14f);
    pb->g(3.14f);
    pb->h(3.14f);
    pd->h(3.14f);
    return 0;
}

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

答:Base类中函数void g(); 和void h();与Derived类中的函数void g(); 和void h();函数名相同,参数类型不同,构成了函数重载。

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

2 . 分析并调试下列程序
  1. <span style="font-size:18px;">//sy6_3.cpp</span>  
  2. <span style="font-size:18px;">#include<iostream></span>  
  3. <span style="font-size:18px;">using namespace std;</span>  
  4. <span style="font-size:18px;">class Base</span>  
  5. <span style="font-size:18px;">{</span>  
  6. <span style="font-size:18px;">    public:</span>  
  7. <span style="font-size:18px;">        void f(int x){cout<<"Base::f(int)"<<x<<endl;}</span>  
  8. <span style="font-size:18px;">        void f(float x){cout<<"Base::f(float)"<<x<<endl;}</span>  
  9. <span style="font-size:18px;">        virtual void g(void){cout<<"Base::g(void)"<<endl;}</span>  
  10. <span style="font-size:18px;">};</span>  
  11. <span style="font-size:18px;">class Derived:public Base</span>  
  12. <span style="font-size:18px;">{</span>  
  13. <span style="font-size:18px;">    public:</span>  
  14. <span style="font-size:18px;">        virtual void g(void){cout<<"Derived::g(void}"<<endl;}</span>  
  15. <span style="font-size:18px;">};</span>  
  16. <span style="font-size:18px;">int main()</span>  
  17. <span style="font-size:18px;">{</span>  
  18. <span style="font-size:18px;">    Derived d;</span>  
  19. <span style="font-size:18px;">    Base *pb=&d;</span>  
  20. <span style="font-size:18px;">    pb->f(42);</span>  
  21. <span style="font-size:18px;">    pb->f(3.14f);</span>  
  22. <span style="font-size:18px;">    pb->g();</span>  
  23. <span style="font-size:18px;">    return 0;</span>  
  24. <span style="font-size:18px;">}</span>  
//sy6_3.cpp
#include<iostream>
using namespace std;
class Base
{
    public:
        void f(int x){cout<<"Base::f(int)"<<x<<endl;}
        void f(float x){cout<<"Base::f(float)"<<x<<endl;}
        virtual void g(void){cout<<"Base::g(void)"<<endl;}
};
class Derived:public Base
{
    public:
        virtual void g(void){cout<<"Derived::g(void}"<<endl;}
};
int main()
{
    Derived d;
    Base *pb=&d;
    pb->f(42);
    pb->f(3.14f);
    pb->g();
    return 0;
}
(1)找出以上程序中使用了重载和覆盖函数。

答:Base类中函数void f(); 在同一作用域中,函数名相同,参数类型不同,构成了函数重载。

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


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


3. 分析并调试下列程序
  1. <span style="font-size:16px;">//sy6_3.cpp</span>  
  2. <span style="font-size:16px;">#include<iostream></span>  
  3. <span style="font-size:16px;">using namespace std;</span>  
  4. <span style="font-size:16px;">class Point</span>  
  5. <span style="font-size:16px;">{</span>  
  6. <span style="font-size:16px;">    public:</span>  
  7. <span style="font-size:16px;">        Point(double i,double j){x=i;y=j;}</span>  
  8. <span style="font-size:16px;">        double Area(){return 0.0;}</span>  
  9. <span style="font-size:16px;">    private:</span>  
  10. <span style="font-size:16px;">        double x,y;</span>  
  11. <span style="font-size:16px;">};</span>  
  12. <span style="font-size:16px;">class Rectangle:public Point</span>  
  13. <span style="font-size:16px;">{</span>  
  14. <span style="font-size:16px;">    public:</span>  
  15. <span style="font-size:16px;">        Rectangle(double i,double j,double k,double l):Point(i,j){w=k;h=l;}</span>  
  16. <span style="font-size:16px;">        double Area(){return w*h;}</span>  
  17. <span style="font-size:16px;">    private:</span>  
  18. <span style="font-size:16px;">        double w,h;</span>  
  19. <span style="font-size:16px;">};</span>  
  20. <span style="font-size:16px;">int main()</span>  
  21. <span style="font-size:16px;">{</span>  
  22. <span style="font-size:16px;">    Point p(3.5,7);</span>  
  23. <span style="font-size:16px;">    double A=p.Area();</span>  
  24. <span style="font-size:16px;">    cout<<"Area= "<<A<<endl;</span>  
  25. <span style="font-size:16px;">    Rectangle r(1.2,3,5,7.8);</span>  
  26. <span style="font-size:16px;">    A=r.Area();</span>  
  27. <span style="font-size:16px;">    cout<<"Area= "<<A<<endl;</span>  
  28. <span style="font-size:16px;">    return 0;</span>  
  29. <span style="font-size:16px;">}</span>  
//sy6_3.cpp
#include<iostream>
using namespace std;
class Point
{
    public:
        Point(double i,double j){x=i;y=j;}
        double Area(){return 0.0;}
    private:
        double x,y;
};
class Rectangle:public Point
{
    public:
        Rectangle(double i,double j,double k,double l):Point(i,j){w=k;h=l;}
        double Area(){return w*h;}
    private:
        double w,h;
};
int main()
{
    Point p(3.5,7);
    double A=p.Area();
    cout<<"Area= "<<A<<endl;
    Rectangle r(1.2,3,5,7.8);
    A=r.Area();
    cout<<"Area= "<<A<<endl;
    return 0;
}

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

程序的输出结果如下:

4. 分析并调试下列程序
  1. <span style="font-size:16px;">//sy6_4.cpp</span>  
  2. <span style="font-size:16px;">#include<iostream></span>  
  3. <span style="font-size:16px;">using namespace std;</span>  
  4. <span style="font-size:16px;">const double PI=3.1415;</span>  
  5. <span style="font-size:16px;">class Shap</span>  
  6. <span style="font-size:16px;">{</span>  
  7. <span style="font-size:16px;">    public:</span>  
  8. <span style="font-size:16px;">        virtual double Area()=0;</span>  
  9. <span style="font-size:16px;">};</span>  
  10. <span style="font-size:16px;">class Triangle:public Shap</span>  
  11. <span style="font-size:16px;">{</span>  
  12. <span style="font-size:16px;">    public:</span>  
  13. <span style="font-size:16px;">        Triangle(double h,double w){H=h;W=w;}</span>  
  14. <span style="font-size:16px;">        double Area(){return 0.5*H*W;}</span>  
  15. <span style="font-size:16px;">    private:</span>  
  16. <span style="font-size:16px;">        double H,W;</span>  
  17. <span style="font-size:16px;">};</span>  
  18. <span style="font-size:16px;">class Rectangle:public Shap</span>  
  19. <span style="font-size:16px;">{</span>  
  20. <span style="font-size:16px;">    public:</span>  
  21. <span style="font-size:16px;">        Rectangle(double h,double w){H=h;W=w;}</span>  
  22. <span style="font-size:16px;">        double Area(){return H*W;}</span>  
  23. <span style="font-size:16px;">    private:</span>  
  24. <span style="font-size:16px;">        double H,W;</span>  
  25. <span style="font-size:16px;">};</span>  
  26. <span style="font-size:16px;">class Circle:public Shap</span>  
  27. <span style="font-size:16px;">{</span>  
  28. <span style="font-size:16px;">    public:</span>  
  29. <span style="font-size:16px;">        Circle(double r){R=r;}</span>  
  30. <span style="font-size:16px;">        double Area(){return PI*R*R;}</span>  
  31. <span style="font-size:16px;">    private:</span>  
  32. <span style="font-size:16px;">        double R;</span>  
  33. <span style="font-size:16px;">};</span>  
  34. <span style="font-size:16px;">class Square:public Shap</span>  
  35. <span style="font-size:16px;">{</span>  
  36. <span style="font-size:16px;">    public:</span>  
  37. <span style="font-size:16px;">        Square(double s){S=s;}</span>  
  38. <span style="font-size:16px;">        double Area(){return S*S;}</span>  
  39. <span style="font-size:16px;">    private:</span>  
  40. <span style="font-size:16px;">        double S;</span>  
  41. <span style="font-size:16px;">};</span>  
  42. <span style="font-size:16px;">double Total(Shap *s[],int n)</span>  
  43. <span style="font-size:16px;">{</span>  
  44. <span style="font-size:16px;">    double sum=0;</span>  
  45. <span style="font-size:16px;">    for(int i=0;i<n;i++)</span>  
  46. <span style="font-size:16px;">        sum+=s[i]->Area();</span>  
  47. <span style="font-size:16px;">    return sum;</span>  
  48. <span style="font-size:16px;">}</span>  
  49. <span style="font-size:16px;">int main()</span>  
  50. <span style="font-size:16px;">{</span>  
  51. <span style="font-size:16px;">   Shap *s[5];</span>  
  52. <span style="font-size:16px;">   s[0]=new Square(8.0);</span>  
  53. <span style="font-size:16px;">   s[1]=new Rectangle(3.0,8.0);</span>  
  54. <span style="font-size:16px;">   s[2]=new Square(12.0);</span>  
  55. <span style="font-size:16px;">   s[3]=new Circle(8.0);</span>  
  56. <span style="font-size:16px;">   s[4]=new Triangle(5.0,4.0);</span>  
  57. <span style="font-size:16px;">   double sum=Total(s,5);</span>  
  58. <span style="font-size:16px;">   cout<<"SUM = "<<sum<<endl;</span>  
  59. <span style="font-size:16px;">    return 0;</span>  
  60. <span style="font-size:16px;">}</span>  
//sy6_4.cpp
#include<iostream>
using namespace std;
const double PI=3.1415;
class Shap
{
    public:
        virtual double Area()=0;
};
class Triangle:public Shap
{
    public:
        Triangle(double h,double w){H=h;W=w;}
        double Area(){return 0.5*H*W;}
    private:
        double H,W;
};
class Rectangle:public Shap
{
    public:
        Rectangle(double h,double w){H=h;W=w;}
        double Area(){return H*W;}
    private:
        double H,W;
};
class Circle:public Shap
{
    public:
        Circle(double r){R=r;}
        double Area(){return PI*R*R;}
    private:
        double R;
};
class Square:public Shap
{
    public:
        Square(double s){S=s;}
        double Area(){return S*S;}
    private:
        double S;
};
double Total(Shap *s[],int n)
{
    double sum=0;
    for(int i=0;i<n;i++)
        sum+=s[i]->Area();
    return sum;
}
int main()
{
   Shap *s[5];
   s[0]=new Square(8.0);
   s[1]=new Rectangle(3.0,8.0);
   s[2]=new Square(12.0);
   s[3]=new Circle(8.0);
   s[4]=new Triangle(5.0,4.0);
   double sum=Total(s,5);
   cout<<"SUM = "<<sum<<endl;
    return 0;
}
程序的输出结果如下:
(1)指出抽象类。
(2)指出纯虚函数,并说明它的作用。
(3)每个类的作用是什么?整个程序的作用是什么?
5. 某学校对教师每个月工资的计算规定如下:固定工资+课时补贴;教授的固定工资为5000元,每个课时补贴50;副教授的固定工资为3000,每个课时补贴30元;讲师的固定工资为2000元,每个课时补贴20元。定义教师抽象类,派生不同职称的教师类,编写程序求若干个教师的月工资。(sy6_5.cpp)
  1. <span style="font-family:SimSun;font-size:16px;">//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.   
  11. class Professor:public Teacher  
  12. {  
  13. private:  
  14.     char name[128];  
  15.     int lessons;  
  16. public:  
  17.     Professor()  
  18.     {  
  19.         cout<<"请输入姓名:";  
  20.         cin>>name;  
  21.         cout<<"请输入课时:";  
  22.         cin>>lessons;  
  23.     };  
  24.     int Salary()  
  25.     {  
  26.         return (5000+lessons*50);  
  27.     };  
  28.     void Print(int money)  
  29.     {  
  30.         cout<<"职称:教授 姓名:"<<name<<" 薪水:"<<money<<endl<<endl;  
  31.     };  
  32. };  
  33.   
  34. class AssociateProfessor:public Teacher  
  35. {  
  36. private:  
  37.     char name[128];  
  38.     int lessons;  
  39. public:  
  40.     AssociateProfessor()  
  41.     {  
  42.         cout<<"请输入姓名:";  
  43.         cin>>name;  
  44.         cout<<"请输入课时:";  
  45.         cin>>lessons;  
  46.     };  
  47.     int Salary()  
  48.     {  
  49.         return (3000+lessons*30);  
  50.     };  
  51.     void Print(int money)  
  52.     {  
  53.         cout<<"职称:副教授 姓名:"<<name<<" 薪水:"<<money<<endl<<endl;  
  54.     };  
  55. };  
  56.   
  57. class Lecturer:public Teacher  
  58. {  
  59. private:  
  60.     char name[128];  
  61.     int lessons;  
  62. public:  
  63.     Lecturer()  
  64.     {  
  65.         cout<<"请输入姓名:";  
  66.         cin>>name;  
  67.         cout<<"请输入课时:";  
  68.         cin>>lessons;  
  69.     };  
  70.     int Salary()  
  71.     {  
  72.         return (2000+lessons*20);  
  73.     };  
  74.     void Print(int money)  
  75.     {  
  76.         cout<<"职称:讲师 姓名:"<<name<<"薪水:"<<money<<endl<<endl;  
  77.     };  
  78. };  
  79.   
  80. int main()  
  81. {  
  82.     Teacher *t = NULL;  
  83.   
  84.     int money=0;  
  85.   
  86.      t = new Professor();  
  87.     money = t->Salary();  
  88.     t->Print(money);  
  89.     delete t;  
  90.   
  91.   
  92.     t = new AssociateProfessor();  
  93.     money = t->Salary();  
  94.     t->Print(money);  
  95.     delete t;  
  96.   
  97.   
  98.     t = new Lecturer();  
  99.     money = t->Salary();  
  100.     t->Print(money);  
  101.     delete t;  
  102.     t = NULL;  
  103.     return 0;  
  104. }</span>  
//sy6_5.cpp
#include <iostream>
using namespace std;
class Teacher
{
public:
    virtual int Salary()=0;
    virtual void Print(int)=0;
};

class Professor:public Teacher
{
private:
    char name[128];
    int lessons;
public:
    Professor()
    {
        cout<<"请输入姓名:";
        cin>>name;
        cout<<"请输入课时:";
        cin>>lessons;
    };
    int Salary()
    {
        return (5000+lessons*50);
    };
    void Print(int money)
    {
        cout<<"职称:教授 姓名:"<<name<<" 薪水:"<<money<<endl<<endl;
    };
};

class AssociateProfessor:public Teacher
{
private:
    char name[128];
    int lessons;
public:
    AssociateProfessor()
    {
        cout<<"请输入姓名:";
        cin>>name;
        cout<<"请输入课时:";
        cin>>lessons;
    };
    int Salary()
    {
        return (3000+lessons*30);
    };
    void Print(int money)
    {
        cout<<"职称:副教授 姓名:"<<name<<" 薪水:"<<money<<endl<<endl;
    };
};

class Lecturer:public Teacher
{
private:
    char name[128];
    int lessons;
public:
    Lecturer()
    {
        cout<<"请输入姓名:";
        cin>>name;
        cout<<"请输入课时:";
        cin>>lessons;
    };
    int Salary()
    {
        return (2000+lessons*20);
    };
    void Print(int money)
    {
        cout<<"职称:讲师 姓名:"<<name<<"薪水:"<<money<<endl<<endl;
    };
};

int main()
{
    Teacher *t = NULL;

    int money=0;

     t = new Professor();
    money = t->Salary();
    t->Print(money);
    delete t;


    t = new AssociateProfessor();
    money = t->Salary();
    t->Print(money);
    delete t;


    t = new Lecturer();
    money = t->Salary();
    t->Print(money);
    delete t;
    t = NULL;
    return 0;
}
程序输出结果如下:


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

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

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

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

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

   动态联编是指联编在程序运行时动态地进行,根据当时的情况来确定调用哪个同名函数,实际上是在运行时虚函数的实现。这种联编又称为晚期联编,或动态束定。动态联编对成员函数的选择是基于对象的类型,针对不同的对象类型将做出不同的编译结果。C++中一般情况下的联编是静态联编,但是当涉及到多态性和虚函数时应该使用动态联编。动态联编的优点是灵活性强,但效率低。

动态联编的条件:
①必须把动态联编的行为定义为类的虚函数。
②类之间应满足子类型关系,通常表现为一个类从另一个类公有派生而来。
③必须先使用基类指针指向子类型的对象,然后直接或者间接使用基类指针调用虚函数。

实验总结

  通过本次实验我了解静态联编的动态联编的概念以及静态联编和动态联编的区别,了解了什么是重载和覆盖函数掌握动态联编的条件。在同一个作用域内,函数名相同,参数列表不同(参数个数不同,或者参数类型不同,或者参数个数和参数类型都不同),返回值类型可相同也可不同,这种情况叫做C++的重载。而覆盖又被叫做重写,是当在子类中定义一个与父类完全相同的虚函数时,则称子类的这个函数重写了父类的这个虚函数。在之前一直都不明白这两者的概念含义,不知道怎么去运用,通过老师的讲解和实验的操作,大概了解了是怎么一回事,但是还需要在课下花时间去练习。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值