实验5 类的继承、派生和多态(2)

实验5 类的继承、派生和多态(2) :
验证性实验:
1.
截图:

代码:

// 示例:多层继承,没有使用虚函数 
#include <iostream>
using namespace std;

// 基类Base1 
class Base1 {
    public:
        void display() const {cout << "Base1::display()" << endl; }
};

// 派生类Base2,公有继承自Base1 
class Base2:public Base1{
    public:
        void display() const { cout << "Base2::display()" << endl; }
};

// 派生类Derived,公有继承自Base2 
class Derived: public Base2 {
    public:
        void display() const { cout << "Derived::display()" << endl;}
};

void fun(Base1 *ptr) {
    ptr->display();
}


int main() {
    
    Base1 base1;
    Base2 base2;
    Derived derived;
    
    // 观察:通过"对象名.成员名"访问类族中同名成员函数时运行结果
    base1.display();
    base2.display();
    derived.display();
     
    // 观察:通过公共接口函数fun(),利用基类指针访问同名成员函数时运行结果 
    fun(&base1);
    fun(&base2);
    fun(&derived);
    
    return 0;
}

本题没有使用虚函数,因而根据同名覆盖原则,子类中的所有display()都继承父类,因而结果都为Base1:display();

2.

截图:

本题使用了纯虚函数,因而先按基类构造函数的顺序,再按内嵌函数的顺序进行,得到结果。两个实验的指针分别指向Base1中的display(),和子类Base中display()。

代码:

// 示例:多层继承,使用虚函数 
#include <iostream>
using namespace std;

// 基类Base1 
class Base1 {
    public:
        virtual void display() const {cout << "Base1::display()" << endl; }  // 相较于ex1_1.cpp, 基类Base1中成员函数前添加了关键字virtual     
};

// 派生类Base2,公有继承自Base1 
class Base2:public Base1{
    public:
        void display() const { cout << "Base2::display()" << endl; }
};

// 派生类Derived,公有继承自Base2 
class Derived: public Base2 {
    public:
        void display() const { cout << "Derived::display()" << endl;}
};

void fun(Base1 *ptr) {
    (*ptr).display();
}


int main() {
    
    Base1 base1;
    Base2 base2;
    Derived derived;
    
    // 观察:通过"对象名.成员名"访问类族中同名成员函数时运行结果 
    base1.display();
    base2.display();
    derived.display();
     
    // 观察:通过公共接口函数fun(),利用基类指针访问同名成员函数时运行结果 
    fun(&base1);
    fun(&base2);
    fun(&derived);
    
    return 0;
}

3.

截图:

代码:

#include <iostream>
#include <cmath>
using namespace std;
const float PI = 3.14;
 
//抽象类Shape 
class Shape {
    public:
        virtual float area();   // 纯虚函数 
}; 

// 派生类Rectangle供有继承自类Shape 
class Rectangle: public Shape {
    public:
        Rectangle() {}
        Rectangle(float l, float w): length(l), width(w) { } 
        float area() { return length*width; }
    private:
        float length, width;
};

// 派生类Cirle公有继承自类Shape
class Circle: public Shape {
    public:
        Circle() {}
        Circle(float r): radius(r) { }
        float area() { return PI*radius*radius; }
    private:
        float radius;
}; 


// 派生类Triangle公有继承自类Shape 
class Triangle: public Shape {
    public:
        Triangle() {} 
        Triangle(float a, float b, float c):side1(a), side2(b), side3(c) { }
        float area() { 
            float t;
            t = (side1 + side2 + side3) / 2;
            return sqrt( t*(t-side1)*(t-side2)*(t-side3) );
        }
    private:
        float side1, side2, side3; 
};

// 接口函数,为打印图形面积提供了一个统一的功能接口,用于打印图形面积 
// 形参是指向基类的指针,按照继承和派生机制中的赋值兼容原则,它也可以指向派生类的对象 
void printArea(Shape *p) {
    cout << p->area() << endl;
}

int main() {
    Rectangle rect(3,4);
    Circle  cc(2);
    Triangle  tt(3,4,5);
    
    printArea(&rect);
    printArea(&cc);
    printArea(&tt);
    
    return 0;
}

4.

电子宠物:
代码:

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 class MachinePets {
 5 public:
 6     virtual string talk()=0;
 7     virtual string getnickname() = 0;
 8 };
 9 class PetCats :public MachinePets {
10 public:
11     PetCats() {}
12     PetCats(string s) :nickname(s) {}
13     string getnickname();
14     string talk() {
15         string a = "miao miao";
16         return a;
17     }
18 private:
19     string nickname;
20 };
21 class PetDogs :public MachinePets {
22 public:
23     PetDogs() {}
24     PetDogs(string s) :nickname(s) {}
25     string getnickname();
26     string talk() {
27         string a = "wang wang";
28         return a;
29     }
30 private:
31     string nickname;
32 };
33 string PetCats::getnickname()
34 {
35     return nickname;
36 }
37 string PetDogs::getnickname()
38 {
39     return nickname;
40 }
41 void play(MachinePets* f)
42 {
43     cout <<f->getnickname()<<" "<<"says: "<< f->talk() << endl;
44 }
45 int main() {
46     PetCats cat("miku");
47     play(&cat); // 按照play()形参,传递参数
48     // 按照play()形参,传递参数
49     PetDogs dog("da huang");
50     play(&dog);
51     return 0;
52 }
View Code

截图:

本来此题按照上一题的解法并不困难,但我不小心将虚函数后多加了const;

virtual string talk()const=0 ;

错误 C2259 “PetCats”: 不能实例化抽象类 ConsoleApplication14 C:\Users\asus\source\repos\ConsoleApplication14\ConsoleApplication14.cpp 46

就是由于这个const,抽象类中拥有const,而派生类中没有const,因而会导致编译器将其看做两个不同的函数,会以为talk()没有重写,派生类依旧是抽象类,因而导致错误。
因而const一定不能前有后舍。
5.
rpg

猜你喜欢

转载自www.cnblogs.com/lszz/p/10923470.html