面向對象作業(繼承、多態、虛函數、純虛函數、抽象類)

1. There is a student class, including the student’s name, grades, and requirements:

  • Design a friend function compare() to compare the grade of two students.
  • Define an object array in the main() function to store the input student data, and find the student with the highest score and the lowest score.
#include <bits/stdc++.h>
using namespace std;

class student {
    friend bool compare(student* a, student* b);
private:
    string name;
    int grades;
    string requirements;
public:
    student(string name, int grades, string requirements);
    ~student();

    string getName() {
        return this->name;
    }
};

student::student(string name, int grades, string requirements) {
    this->name = name;
    this->grades = grades;
    this->requirements = requirements;
}

student::~student() {

}

bool compare(student* a, student* b) {
    return a->grades > b->grades;
}

int main() {
    int n;
    cin >> n;
    student* stu[1000];
    for (int i = 1; i <= n; i++) {
        string name;
        int grades;
        string requirements;
        cin >> name >> grades >> requirements;
        stu[i] = new student(name, grades, requirements);
    }
    sort(stu + 1, stu + n + 1, compare);
    cout << "The highest score: " << stu[1]->getName() << endl;
    cout << "The lowest score: " << stu[n]->getName() << endl;
    return 0;
}

2. Define an abstract class Shape, including a pure virtual function perimeter, whose function is to calculate the perimeter of the graph. There are three classes derived from Shape:

  • Triangle, the data member includes the length of three sides (a, b, c);
  • Rectangle (rectangle), data members include width (width) and height (height);
  • Circle, the data member is a radius.
  • Reasonably use polymorphism to realize the perimeter function to calculate the perimeter of triangles, rectangles, and circles.
  • Create triangle objects, rectangle objects and circle objects in main () and display their information.
#include <bits/stdc++.h>
using namespace std;

class Shape {
public:
    virtual double perimeter() = 0;
};

class Triangle : public Shape {
private:
    int length;
public:
    Triangle(int length) : length(length) {}
    double perimeter() {
        return 3 * length;
    }
};

class Rectangle : public Shape {
private:
    int width;
    int height;
public:
    Rectangle(int width, int height) : width(width), height(height) {}
    double perimeter() {
        return 2 * (width + height);
    }
};

class Circle : public Shape {
private:
    int radius;
public:
    Circle(int radius) : radius(radius) {}
    double perimeter() {
        return 2 * M_PI * radius;
    }
};

int main() {
    Shape* triangle = new Triangle(1);
    Shape* rectangle = new Rectangle(2, 3);
    Shape* circle = new Circle(1);
    cout << triangle->perimeter() << endl;
    cout << rectangle->perimeter() << endl;
    cout << circle->perimeter() << endl;
    return 0;
}

3. Define the Person class. The Teacher class and the Cadre class are derived from Person. Requirements are as follows:

  • Data members:
    • The data members included in the Person class include name, age, and gender.
    • Include data members in the Teacher class: position.
    • Include data members in the Cadre class: work, salary.
  • Member function:
    • Define member functions in the class body (including construction and destructor functions according to the actual situation)
    • Each class has a display information function (Show)
    • Create a Teacher object and a Cadre object in main() and display their information.
#include <bits/stdc++.h>
using namespace std;

class Person {
private:
    string name;
    int age;
    string gender;
public:
    Person(string name, int age, string gender);
    ~Person();

    void show();
};

Person::Person(string name, int age, string gender) : name(name), age(age), gender(gender) {

}

Person::~Person() {

}

class Teacher : public Person {
private:
    string position;
public:
    Teacher(string name, int age, string gender, string position);
    ~Teacher();

    void show();
};

Teacher::Teacher(string name, int age, string gender, string position) : Person(name, age, gender), position(position) {

}

Teacher::~Teacher() {

}

class Cadre : public Person {
private:
    string work;
    string salary;
public:
    Cadre(string name, int age, string gender, string work, string salary);
    ~Cadre();

    void show();
};

Cadre::Cadre(string name, int age, string gender, string work, string salary) : Person(name, age, gender), work(work), salary(salary)  {

}

Cadre::~Cadre() {

}

void Person::show() {
    cout << name << " " << age << " " << gender << " ";
}

void Teacher::show() {
    Person::show();
    cout << position << endl;
}

void Cadre::show() {
    Person::show();
    cout << work << " " << salary << endl;
}

int main() {
    Teacher* teacher = new Teacher("xiaoming", 18, "male", "teacher");
    Cadre* cadre = new Cadre("xiaohong", 20, "female", "student", "1000");
    teacher->show();
    cadre->show();
    return 0;
}

4. Define a base class Animal, which contains two private data members, one is the name of the animal (for example, “Fido” or “Yogi”), and the other is the weight of the animal.

  • This class also contains a public member function who(), which can display the animal’s name and weight.
  • Using Animal as a public base class, derive two classes Lion and Aardvark.
  • Write a main() function to create Lion and Aardvark objects (“Leo”, 400 points; “Algernon”, 50 points).
  • Calling the who() member for the derived class object indicates that the who() member is inherited in the two derived classes.
#include <bits/stdc++.h>
using namespace std;

class Animal {
private:
    string name;
    int weight;
public:
    void who() {
        cout << name << " " << weight << endl;
    }

    Animal(string name, int weight);
};

Animal::Animal(string name, int weight) {
    this->name = name;
    this->weight = weight;
}

class Lion : public Animal {
public:
    Lion(string name, int weight);
};

Lion::Lion(string name, int weight) : Animal(name, weight) {

}

class Aardvark : public Animal {
public:
    Aardvark(string name, int weight);

};

Aardvark::Aardvark(string name, int weight) : Animal(name, weight) {

}

int main() {
    Lion* lion = new Lion("Leo", 400);
    Aardvark* aardvark = new Aardvark("Algernon", 50);
    lion->who();
    aardvark->who();
    return 0;
}

筆記

派生類
  • 派生類定義
    • 派生類定義格式
    • class 派生類名 : 繼承方式 基類名 {
          // 派生類新增的數據成員和成員函數
      };
      
    • 三種繼承方式
      • public: 公有繼承
      • private: 私有繼承
      • protected: 保護繼承
    • 從繼承源上分
      • 單繼承:指每個派生類只直接繼承了一個基類的特征
      • class B : public A {};
        
      • 多繼承:指多個基類派生出一個派生類的繼承關係,多繼承的派生類直接繼承了不止一個基類的特征
      • class C : public A, protected B {};
        
  • 派生類訪問控制
  • 基類
    • class A {
      public:
          int a;
      protected:
          int b;
      private:
          int c;
      };
      
  • 公有繼承
    • class B : public A {
      public:
          int a;
      protected:
          int b;
      不可访问:
          int c;
      };
      
  • 保護繼承
    • class B : public A {
      protected:
          int a;
          int b;
      不可访问:
          int c;
      };
      
  • 私有繼承
    • class B : public A {
      private:
          int a;
          int b;
      不可访问:
          int c;
      };
      
虛函數

多態簡單的說就是允許將子類類型的指針賦值給父類類型的指針

有如下代碼

#include <bits/stdc++.h>
using namespace std;

class Animal {
public:
    void speak() {
        cout << "animal is speaking" << endl;
    }
};

class Cat : public Animal {
public:
    void speak() {
        cout << "cat is speaking" << endl;
    }
};

class Dog : public Animal {
public:
    void speak() {
        cout << "dog is speaking" << endl;
    }
};

void doSpeak(Animal& animal) {
    animal.speak();
}


int main() {
    Cat cat;
    doSpeak(cat);
    return 0;
}

我們先定義了一個基類,基類裡面有一個speak函數,然後有許多的類繼承該基類,生成了許多個派生類,每個派生類的speak都有重寫過

現在我們希望只聲明一個函數,不同的派生類調用時執行的是自己的成員函數。即貓調用時應該是貓在說話,狗調用時應該是狗在說話

但是按照上述寫法,輸出的是animal is speaking

因為參數裡面的類是Animal,故地址早就綁定好了

地址早就綁定了,屬於靜態聯編

如果想調用小貓說話,這個時候函數的地址就不能早綁定好

而是在運行階段再去綁定函數地址,屬於地址晚綁定,叫動態聯編

也就是說父類調用了子類的成員函數

那麼怎樣去動態聯編呢

只要在類的成員函數前面加上一個virtual,這個函數的本質就變成了虛函數

派生類的成員函數前加不加virtual均可

再運行後,輸出的就是cat is speaking了

這樣也就是說運行時會編譯器會動態地去找傳入的對象,再去綁定地址

修改後的代碼如下

#include <bits/stdc++.h>
using namespace std;

class Animal {
public:
    virtual void speak() {
        cout << "animal is speaking" << endl;
    }
};

class Cat : public Animal {
public:
    void speak() {
        cout << "cat is speaking" << endl;
    }
};

class Dog : public Animal {
public:
    void speak() {
        cout << "dog is speaking" << endl;
    }
};

void doSpeak(Animal& animal) {
    animal.speak();
}


int main() {
    Cat cat;
    doSpeak(cat);
    return 0;
}
抽象類和純虛函數

在設計時,嘗嘗希望基類僅僅作為其派生類的一個接口

這就是說,僅想對基類進行向上類型轉換,使用它的接口,而不希望用戶實際的創建一個基類的對象

同時創建一個純虛函數允許接口中放置成員原函數,而不一定要提供一段可能對這個函數毫無意義的代碼

做到這點,可以在基類中加入至少一個純虛函數,使得基類稱為抽象類

抽象类的子类必须要重写父类中的纯虚函数,否则也属于抽象类,无法实例化

语法:

virtual int func() = 0;

多態的實例:加減乘法計算器

#include <bits/stdc++.h>
using namespace std;

class AbstractCalculator {
public:
    virtual int getResult() = 0;

    int m_A;
    int m_B;
};

class AddCalculator : public AbstractCalculator {
public:
    virtual int getResult() {
        return m_A + m_B;
    }
};

class SubCalculator : public AbstractCalculator {
public:
    virtual int getResult() {
        return m_A - m_B;
    }
};

class MulCalculator : public AbstractCalculator {
public:
    virtual int getResult() {
        return m_A * m_B;
    }
};

class Test : public AbstractCalculator {
    int getResult() { return 0; };
};

int main() {
    AbstractCalculator* calculator = new AddCalculator;

    calculator->m_A = 100;
    calculator->m_B = 200;

    cout << calculator->getResult() << endl;

    delete calculator;

    calculator = new SubCalculator;
    calculator->m_A = 100;
    calculator->m_B = 200;

    cout << calculator->getResult() << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DoubleQ666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值