1. 程式人生 > >實驗6:類的繼承和多態

實驗6:類的繼承和多態

構造函數 height github eat 主程 初始化列表 HA res 元素

南京信息工程大學實驗報告

實驗名稱 類的繼承和多態 實驗日期 2018-5-29 得分 指導教師 耿學華 計軟院 專業 計嵌+軟嵌 年級 2017 級 班次 (1) 姓名 施昊陽 學號 20161334026

一、實驗目的

  • 理解類的繼承和派生機制
  • 掌握派生類的定義和使用
  • 掌握派生類成員的標識與訪問中同名覆蓋原則、二元作用域分辨符和虛基類的用法
  • 掌握派生類構造函數和析構函數的定義及調用次序
  • 理解運算符重載的目的,掌握運算符重載函數的編寫方法

二、實驗準備

  • 類的繼承和派生
    請結合第 7 章課件和教材復習以下內容:
    • 引入繼承和派生機制的目的
    • 基本概念:繼承、派生、基類、直接基類、間接基類、派生類
    • 語法:
      • 派生類定義的語法格式(單重繼承、多重繼承);
      • 派生類構造函數極其初始化列表寫法
    • 派生類成員的標識與訪問
      • 同名覆蓋指的是什麽?
      • 二元作用域分辨符在什麽情況下使用?
      • 什麽是虛基類?引入虛基類的目的是什麽?如何使用?
  • 運算符重載
    請結合第 8 章課件和教材學習以下內容:
    • 運算符重載的目的
    • 運算符重載的規則和限制
    • 運算符重載函數的語法格式
    • 運算符重載時,究竟重載為類的成員函數,還是友元,還是普通函數,需要綜合考慮哪些因素?

三、實驗內容

  • 某計算機硬件系統,為了實現特定的功能,在某個子模塊設計了 ABC 三款芯片用於
    數字計算。各個芯片的計算功能如下:
    A 芯片:計算兩位整數的加法(m+n)、計算兩位整數的減法(m-n)

    B 芯片:計算兩位整數的加法(m+n)、計算兩位整數的乘法(m*n)
    C 芯片:計算兩位整數的加法(m+n)、計算兩位整數的除法(m/n)
    為 ABC 三個芯片分別定義類,描述上述芯片的功能,並在 main 函數中測試這三個類。
    (提示:利用類的繼承和派生,抽象出共有屬性和操作作為基類。)

  • 定義一個車(vehicle)基類,具有數據成員 maxspeed, weight(均為 int 型), 函數成員 run(), stop(),由此派生出自行車(bicycle)類、汽車(motorcar)類。其中, bicycle 類新增數據成員高度(height),motorcar 類新增數據成員座位數(seatnum)屬性。再從 bicycle 和 motorcar 派生出摩托車(motorcycle)類,並在主程序中測試這個類。(每個類都要求定義構造函數和析構函數)

    (提示: ① 註意把 vehicle 設置為虛基類; ② run(), stop()函數體,通過輸出字符串run, stop 簡單模擬。)

  • 基於「實驗 4 類和對象-2」中設計並實現的類 Fraction,創建派生類 iFraction,用以
    描述如下形式的分數:
    \(1\frac 2 3\)
    要求:
    • 更新 Fraction 類
      為 Fraction 類編寫運算符+、-、、/重載函數,實現在 main 函數中直接用+、-、、/進行 Fraction 類運算。
    • 設計並實現派生 iFraction 類
      • 為派生類 iFraction 定義構造函數,實現 iFraction 對象的初始化
      • 為派生類 iFraction 增加一個成員函數,用於在屏幕上顯示 iFraction 對象
    • 設計一個普通函數 convertF()用於對 iFraction 類對象進行規範化處理。(選做
      (提示:把 convertF()設計為 Fraction 類和 iFraction 類的友元函數)
      例如:(更多情形請自行考慮)
      \(\frac 5 3 \to 1 \frac 2 3\)
  • 以多文件結構方式編寫(fraction.h, fraction.cpp, ifraction.h, ifraction.cpp, main.cpp)
    選做
    基於提供的程序文件,補足並擴充程序,實現一個多類型玩家角色扮演遊戲。
    在本次實驗附件包 ex4 中有如下文件:
    container.h, container.cpp, player.h, player.cpp, swordsman.h, swordsman.cpp, main.cpp
    • 閱讀源碼,理解並補足程序,讓程序運行生效。
      其中,程序中出現有????????之處,是需要補足的部分。
    • 畫出這個角色扮演遊戲 UML 類圖,尤其是類和類之間的關系
    • 設計並實現 archer 類和 mage 類。在 UML 類圖中也加進這兩個新類。
    • 修改 main 函數,隨機生成不同角色的敵人,並保證程序正常運行。
    • 為遊戲增加其它元素,完善遊戲的可玩性、趣味性,等。
      (說明:這道涉及虛函數、運行時多態。你可以在第 8 章學完後嘗試編寫,或者,在嘗試編寫這道題的過程中,學習第 8 章虛函數和運行時多態的知識。)

四、實驗結論

  • 實驗內容 1
    • LM51.h

      #include<bits/stdc++.h>
      using namespace std;
      #ifndef _LM51_H
      #define _LM51_H
      class LM51{
      protected:
              int m,n;
      public:
      int plus();
      LM51(int M=2016,int N=133);
      ~LM51();
      }; 
      #endif
    • LM51.cpp

      #include"LM51.h"
      int LM51::plus() {
      cout << "LM51.plus " << endl;
      return m+n;
      }
      LM51::LM51(int M,int N) {
      cout << "Constru
      }ctor LM51 is called" << endl;
      m=M;
      n=N;
      LM51::~LM51() {
      cout << "Deconstructor LM51 is called" << endl;
      }
    • A.h

      #include"LM51.h"
      #ifndef _A_h
      #define _A_h
      class A:public LM51{
      public :
      A(int M=2016,int N=133);
      int minus();
      ~A();   
      };
      #endif
    • A.cpp

      #include"A.h"
      A::A(int M,int N){
      m=M;
      n=N;
      cout << "Constructor A is called" << endl;
      }
      int A::minus() {
      cout << "A.minus " << endl;
      return m-n;
      }
      A::~A() {
      cout << "Deconstructor A is called" << endl;
      }
    • B.h

      #include"LM51.h"
      #ifndef _B_h
      #define _B
      class B:public LM51{
      public :
      B(int M=2016,int N=133);
      int mulip();
      ~B();   
      };
      #endif
    • B.cpp

      #include"B.h"
      B::B(int M,int N){
      m=M;
      n=N;
      cout << "Constructor B is called" << endl;
      }
      int B::mulip() {
      cout << "B.mulip " << endl;
      return m*n;
      }
      B::~B() {
      cout << "Deconstructor B is called" << endl;
      }
    • C.h

      #include"LM51.h"
      #ifndef _C_h
      #define _C
      class C:public LM51{
      public :
      C(int M=2016,int N=133);
      double divi();
      ~C();   
      };
      #endif
    • C.cpp

      #include"C.h"
      C::C(int M,int N){
      m=M;
      n=N;
      cout << "Constructor C is called" << endl;
      }
      double C::divi() {
      cout << "C.divi " << endl;
      return m/n;
      }
      C::~C() {
      cout << "Deconstructor C is called" << endl;
      }
    • Main.cpp

      #include<bits/stdc++.h>
      #include "A.h"
      #include "B.h" 
      #include "C.h"
      using namespace std;
      int main(){
      A a(20,16);
      cout<<a.plus()<<endl;
      cout<<a.minus()<<endl;
      B b(13,1);
      cout<<b.plus()<<endl;
      cout<<b.mulip()<<endl;
      C c(40,26);
      cout<<c.plus()<<endl;
      cout<<c.divi()<<endl;
      return 0;
      }
    • Screenshot:
      技術分享圖片

  • 實驗內容 2
    • vehicle.h

      #ifndef _VEHICLE
      #define _VEHICLE
      class vehicle{
      protected:
      int maxspeed,weight;
      public:
      void run();
      void stop();
      vehicle(int M=100,int W=1000);
      ~vehicle();
      };  
      #endif
    • vehicle.cpp

      #include "vehicle.h"
      void vehicle::run() {
      cout<<"run"<<endl;
      }
      void vehicle::stop() {
      cout<<"stop"<<endl;
      }
      vehicle::vehicle(int M,int W) {
      maxspeed=M;
      weight=W;
      cout<<"Constructor vehicle is called"<<endl;
      }
      vehicle::~vehicle() {
      cout<<"Deconstructor vehicle is called"<<endl;
      }
    • bicycle.h

      #ifndef _BICYCLE
      #define _BICYCLE
      class bicycle:virtual public vehicle{
      protected:
      int height;
      public:
      bicycle(int M=100,int W=1000,int H=2):vehicle(M,W);
      ~bicycle();
      };
      #endif
    • bicycle.cpp

      #include"bicycle.h"
      bicycle::bicycle(int M,int W,int H):vehicle(M,W) {
      height=H;
      cout<<"Constructor bicycle is called"<<endl;
      }
      bicycle::~bicycle() {
      cout<<"Deconstructor bicycle is called"<<endl;
      }
    • motorcar.h

      #ifndef _MOTORCAR
      #define _MOTORCAR
      class motorcar:virtual public vehicle{
      protected:
      int seatnum;
      public:
      motorcar(int M,int W,int H):vehicle(M,W);
      ~motorcar();
      };
      #endif
    • motorcar.cpp

      #include"motocar.h"
      motocar::motorcar(int M,int W,int S):vehicle(M,W) {
      seatnum=S;
      cout<<"Constructor motorcar is called"<<endl;
      }
      motocar::~motorcar() {
      cout<<"Deconstructor motorcar is called"<<endl;
      }
    • motorcycle.h

      #ifndef _MOTORCYCLE
      #define _MOTORCYCLE
      class motorcycle:public bicycle,public motorca{
      public:
      motorcycle(int M=100,int W=1000,int S=4,int H=2):vehicle(M,W);
      ~motorcycle();
      };
      #endif
    • motorcycle.cpp

      #include"motorcycle.h"
      motorcycle::motorcycle(int M,int W,int S,int H):vehicle(M,W) {
      seatnum=S;
      height=H;
      cout<<"Constructor motorcycle is called"<<endl;
      }
      motorcycle::~motorcycle() {
      cout<<"Deconstructor motorcycle is called"<<endl;
      }
    • Main.cpp

      #include"vehicle.h"
      #include"bicycle.h"
      #include"motorcar.h"
      #include"motorcycle.h"
      int main(){
      vehicle a;
      a.run();
      a.stop();
      bicycle b;
      b.run();
      b.stop();
      motorcar c;
      c.run();
      c.stop();
      motorcycle d;
      d.run();
      d.stop();
      return 0;
      }

    -Screenshot:
    技術分享圖片

  • 實驗內容 3
    • iFraction.h

      #include "Fraction.h"
      #ifndef _IFRACTION
      #define _IFRACTION
      class iFraction:public Fraction{
      private:
      int i;
      public:
      iFraction(int t=0,int b=1,int I=0):Fraction(t,b){i=I;}
      iFraction(const iFraction &c0):Fraction(c0){i=c0.i;}
      void print();
      friend iFraction convertF(const iFraction &c0);
      };
      #endif
    • iFraction.cpp

      #include"iFraction.h"
      void iFraction::print() {
      if(top==0){cout<<i<<endl;
      return ;
      }
      cout<<setw(4)<<setfill(' ')<<top<<endl;
      cout<<setw(3)<<setfill(' ')<<i<<'-'<<endl;
      cout<<setw(4)<<setfill(' ')<<bottom<<endl;
      }
      iFraction convertF(const iFraction &c0) {
      iFraction tmp(c0);
      tmp.simplify();
      int tt=tmp.top/tmp.bottom;
      tmp.i+=tt;
      tmp.top%=tmp.bottom;
      return tmp;
      }
    • Fraction.h

      #include<iostream>
      #include<cmath>
      #include <iomanip>
      #ifndef _FRACTION
      #define _FRACTION
      using namespace std;
      class Fraction {
      protected:
      int top, bottom;
      int gcd(int a, int b);
      public:
      Fraction(int t, int b);
      Fraction(int t);
      Fraction();
      void simplify();
      void add(Fraction c0);
      void subtract(Fraction c0);
      void multiple(Fraction c0);
      void divde(Fraction c0);
      bool compare(Fraction c0);
      void readln();
      void writeln();
      double todecimal();
      friend Fraction operator +(const Fraction &c0,const Fraction &c1);
      friend Fraction operator -(const Fraction &c0,const Fraction &c1);
      friend Fraction operator *(const Fraction &c0,const Fraction &c1);
      friend Fraction operator /(const Fraction &c0,const Fraction &c1);
      Fraction &operator +=(const Fraction &c0) {
          bottom = bottom * c0.bottom;
          top = top * c0.bottom + c0.top * bottom;
          simplify();
          return *this; 
      }
      Fraction &operator -=(const Fraction &c0) {
          bottom = bottom * c0.bottom;
          top = top * c0.bottom - c0.top * bottom;
          if(bottom < 0) {
              top = - top;
              bottom = - bottom;
          }
          simplify();
          return *this; 
      }
      Fraction &operator *=(const Fraction &c0) {
          top *= c0.top;
          bottom *= c0.bottom;
          simplify();
          return *this; 
      }
      Fraction &operator /=(const Fraction &c0) {
          if(c0.top == 0) {
              return *this; 
          }
          top *= c0.bottom;
          bottom *= c0.top;
          simplify();
          return *this; 
      }
      };
      #endif
    • Fraction.cpp

      #include"Fraction.h"
      int Fraction::  gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a%b);
      }
      Fraction:: Fraction(int t, int b) {
      top = t;
      bottom = b;
      }
      Fraction:: Fraction(int t) {
      top = t;
      bottom = 1;
      }
      Fraction:: Fraction() {
      top = 0;
      bottom = 1;
      }
      void Fraction:: simplify() {
      if(bottom < 0) {
      top = - top;
      bottom = - bottom;
      }
      int g = gcd(abs(top),abs(bottom));
      top /= g;
      bottom /= g;
      }
      void Fraction:: add(Fraction c0) {
      bottom = bottom * c0.bottom;
      top = top * c0.bottom + c0.top * bottom;
      simplify();
      }
      void Fraction:: subtract(Fraction c0) {
      bottom = bottom * c0.bottom;
      top = top * c0.bottom - c0.top * bottom;
      if(bottom < 0) {
      top = - top;
      bottom = - bottom;
      }
      simplify();
      }
      void Fraction:: multiple(Fraction c0) {
      top *= c0.top;
      bottom *= c0.bottom;
      simplify();
      }
      void Fraction:: divde(Fraction c0) {
      if(c0.top == 0) {
      cout << "Error: Zero can't be divided.\n";
      return ;
      }
      top *= c0.bottom;
      bottom *= c0.top;
      simplify();
      }
      bool Fraction:: compare(Fraction c0) {
      return top * gcd(bottom, c0.bottom) - c0.top
         * gcd(bottom, c0.bottom) > 0 ? true : false;
      }
      void Fraction:: readln() {
      cout << "Plz input the Numerator and Denominator" << endl;
      cin >> top;
      int tmp;
      cin >> tmp;
      while (tmp == 0) {
      cout << "Zero can't be the Denominator, plz try again!" << endl;
      cin >> tmp;
      }
      bottom = tmp;
      }
      void Fraction:: writeln() {
      if(bottom != 1) cout << top << "/" << bottom << endl;
      else cout << top <<endl;
      }
      double Fraction:: todecimal() {
      return (double)top / bottom;
      }
      Fraction operator +(const Fraction &c0,const Fraction &c1) {
      Fraction tmp;
      tmp.bottom = c0.bottom * c1.bottom;
      tmp.top = c1.top * c0.bottom + c0.top * c1.bottom;
      tmp.simplify();
      return tmp;
      }
      Fraction operator -(const Fraction &c0,const Fraction &c1) {
      Fraction tmp;
      tmp.bottom = c0.bottom * c1.bottom;
      tmp.top = c0.top * c1.bottom - c1.top * c0.bottom;
      if(tmp.bottom < 0) {
      tmp.top = - tmp.top;
      tmp.bottom = - tmp.bottom;
      }
      tmp.simplify();
      return tmp;
      }
      Fraction operator *(const Fraction &c0,const Fraction &c1) {
      Fraction tmp;
      tmp.top = c0.top * c1.top;
      tmp.bottom = c0.bottom * c1.bottom;
      tmp.simplify();
      return tmp;
      }
      Fraction operator /(const Fraction &c0,const Fraction &c1) {
      Fraction tmp;
      if(c0.top == 0 || c1.top == 0) {
      return tmp;
      }
      tmp.top = c0.top * c1.bottom;
      tmp.bottom = c0.bottom * c1.top;
      tmp.simplify();
      return tmp;
      }
    • Main.cpp

      #include "Fraction.h"
      #include "iFraction.h"
      int main() {
      Fraction c1 (11,-22);
      Fraction c2 (4);
      Fraction c3 ;
      c1 = c1 + c2;
      cout << "c1 + c2 = ";c1.writeln();
      c1 += c2;
      cout << "c1 += c2 , c1 = ";c1.writeln();
      c1 = c1 - c2;
      cout << "c1 - c2 = ";c1.writeln();
      c1 -= c2;
      cout << "c1 -= c2 , c1 = ";c1.writeln();
      c1 = c1 * c2;
      cout << "c1 * c2 = ";c1.writeln();
      c1 *= c2;
      cout << "c1 *= c2 , c1 = ";c1.writeln();
      c1 = c1 / c2;
      cout << "c1 / c2 = ";c1.writeln();
      c1 /= c2;
      cout << "c1 /= c2 , c1 = ";c1.writeln();
      cout << "c4="<<endl;
      iFraction c4(4,2,-3);
      c4.print();
      c4=convertF(c4);
      cout<<"c4 = convertF(c4) = "<<endl;
      c4.print();
      return 0;
      }
    • Screenshot:
      技術分享圖片

  • 實驗內容4:
    Github Address : https://github.com/shylocks/ex_6_4.git
    *Press Commits Buttom to see changes.
    UML :
    技術分享圖片

五、實驗總結與體會

C++ 與 Java 之間關於“類的繼承與多態”一些概念的重疊:
C++ Java
虛函數 普通函數
純虛函數 抽象函數
抽象類 抽象類
虛基類 接口
(C++先輩萬物之父說)

實驗6:類的繼承和多態