第五章 继承与多态

学习目的

  1. 掌握派生类的定义和使用;
  2. 掌握派生类构造与析构函数的定义;
  3. 掌握重写基类的成员函数;
  4. 掌握通过基类指针或引用实现多态的方法。

5.2 实习任务

5.2.1 实习任务一

现要定义处理 3 维点的类,而又不能直接修改 Point 类,以 Point 类作为基
类派生得到 Point3D,Point3D 的定义和部分功能已经实现,请补充未完成的部
分成员函数。要求构造函数通过初始化列表实现。
在 Point3D 的 getDistance 方法中,通过调用基类的 getDistance 可 以计算出 XY 平面内的距离 dis,再通过 sqrt(disdis+dzdz)即可计算出 3D 空间 内点的距离。

#include <iostream>
#include <cmath>
using namespace std;
class Point{
public:
    Point():x(0), y(0){}//初始化列表
    Point(double newX, double newY){
        setValue(newX, newY);
    }
    Point(const Point &p){
        setValue(p.getX(), p.getY());
    }
    
    //~Point();
    void setValue(double newX, double newY){
        x = newX;
        y = newY;
    }
    double getX()const{return x;}
    double getY()const{return y;}
    double getDistance(const Point &p2)const{
        return sqrt(pow(x-p2.getX(),2)+pow(y-p2.getY(),2));
    }
    friend double getDistance(const Point &p1, const Point &p2){
                return sqrt(pow(p1.getX()-p2.getX(),2)+pow(p1.getY()-p2.getY(),2));
    }
private:
    double x,y;
};
class Point3D : public Point{
public:
    Point3D(double newX=0, double newY=0, double newZ=0):Point(newX, newY){z = newZ;}
    double getZ() const{return z;}
    double getDistance( const Point3D& p)const{
        return sqrt(pow(this->Point::getDistance(p),2)+pow(z-p.z,2));
    }
private: 
    double z;
};


int main()
{
    // Point p1(3,4);
    // Point p2(5,2);
    // double distance = p1.getDistance(p2);
    // cout<<"Distance:"<<distance<<endl;
    // distance = getDistance(p1,p2);
    // cout<<"Distance:"<<distance<<endl;
    Point p1(3, 4), p2(5,3);
    Point3D p1_3D(3,4,6);
    Point3D p2_3D(2,6,9);
    double dis=p1.getDistance(p2); //计算二维点 p1 和 p2 的距离 
    cout<<"Distance between p1 and p2: "<<dis<<endl; 
    dis=p1_3D.getDistance(p2_3D); //计算 3 维点 p1_3D 和 p2_3D 的距离 
    cout<<"Distance between p1_3D and p2_3D: "<<dis<<endl;
    return 0;
}
运行结果:
Distance between p1 and p2: 2.23607
Distance between p1_3D and p2_3D: 3.74166
[Finished in 0.3s]
修改程序
dis=p2.getDistance(p2_3D); //计算点 p1_3D 和 p2 的距离 
    cout<<"Distance between p1_3D and p2: "<<dis<<endl;
Distance between p1_3D and p2: 4.24264
运行成功!
修改程序
dis=p1_3D.getDistance(p2); //计算点 p1_3D 和 p2 的距离 
cout<<"Distance between p1_3D and p2: "<<dis<<endl;
报错
no viable conversion from 'Point' to 'const Point3D'

【 提示】如果某个函数调用需要传递基类对象,可以将派生类对象传递给他, 此时将发生切片效果,只将基类需要的数据复制过去。相反,如果需要 1 个派生类对象,传递基类对象将无法通过编译。

增加构造函数
Point3D(const Point&p):Point(p),z(0){}
运行成功
Distance between p1_3D and p2: 6.40312

【提示】只含有 1 个参数的构造函数称为类型转换构造函数,可以将传入参数类型转换为当前类类型。如果需要将基类对象复制给派生类对象,可以通过类型转换构造函数间接实现。

5.2.2 实习任务二
#include <iostream>
#include <cmath>
using namespace std;
const double PI = 3.14;
class Shape{
public:
    // double virtual getArea()const{
    //  return 0;
    // }
    double virtual getArea()const=0;
    // double virtual getPerimeter()const{
    //  return 0;
    // }
    double virtual getPerimeter()const=0;
};
class Circle: public Shape{
public:
    Circle(double r): radius(r){}
    double getArea() const;
    double getPerimeter() const;
private:
    double radius;
};
double Circle::getArea()const{
    return PI*radius*radius;
} 
double Circle::getPerimeter()const{
    return 2*PI*radius;
}
class Rectangle: public Shape{
public:
    Rectangle(double w, double h): width(w), height(h){}
    double getArea() const;
    double getPerimeter() const;
private:
    double width;
    double height;
};
double Rectangle::getArea()const{
    return width*height;
}
double Rectangle::getPerimeter()const{
    return 2*(width + height);
}
class Triangle: public Shape{
public:
    Triangle(double newA, double newB, double newC):a(newA),b(newB),c(newC){}
    double getArea()const;
    double getPerimeter()const;
private:
    double a,b,c;
};
double Triangle::getArea()const{
    double p = this->getPerimeter() / 2.0;//p是半周长,这个别搞错了
    return sqrt(p*(p-a)*(p-b)*(p-c));

}
double Triangle::getPerimeter()const{
    return a+b+c;
}
void outputInfo(const Shape&sh);
void outputInfo(const Shape& sh){
    cout<<"Area:"<<sh.getArea()<<endl;
    cout<<"Perimeter:"<<sh.getPerimeter()<<endl;
}
int main(){
    //Shape shape0;
    Rectangle shape1(3,4);
    Circle shape2(1.0);
    Triangle shape3(3,4,5);
    shape3.getArea();
    // outputInfo(shape0);
    outputInfo(shape1);
    outputInfo(shape2);
    outputInfo(shape3);

    return 0;
}
运行结果:
Area:12
Perimeter:14
Area:3.14
Perimeter:6.28
Area:6
Perimeter:12
[Finished in 0.3s]

课后练习

#include <iostream>
using namespace std;
class Base{
public:
    void display(){cout<<"Base display"<<endl;}
};
class Derived: public Base{
public:
    void display(){cout<<"Derived display"<<endl;}
};
void display(Base & rr){
    rr.display();
}
int main(){
    Base b;
    Derived d;
    display(b);
    display(d);
    return 0;
}
运行结果:
Base display
Base display
[Finished in 0.3s]

另:

void display(Derived & rr){
    rr.display();
}
int main(){
    Base b;
    Derived d;
    b = d;// d = b报错
    // display(b);
    display(d);
    return 0;
}
Derived display
[Finished in 0.3s]
#include <iostream>
using namespace std;
class Person{
public:
    Person(){
        cout<<"Person constructed!"<<endl;
    }
    ~Person(){
        cout<<"Person destructed!"<<endl;
    }
};
class Student: public Person{
public:
    Student(){cout<<"Student constructed!"<<endl;}
    ~Student(){cout<<"Student destructed"<<endl;}
};
class Teacher: public Person{
public:
    Teacher(){
        cout<<"Teacher constructed!"<<endl;
    }
    ~Teacher(){
        cout<<"Teacher destructed!"<<endl;
    }
    
};
int main(){
    Student s;
    Teacher t;
    return 0;
}

因缺思婷 results ↓

运行结果:
Person constructed!
Student constructed!
Person constructed!
Teacher constructed!
Teacher destructed!
Person destructed!
Student destructed
Person destructed!
[Finished in 0.3s]
#include <iostream>
using namespace std;
class Animal{
public:
    virtual void Report(){cout<<"Report from Animal!"<<endl;}
};
class Tiger: public Animal{
public:
    virtual void Report(){cout<<"Report from Tiger!"<<endl;}
};
class Monkey: public Animal{
public:
    virtual void Report(){
        cout<<"Report from Monkey!"<<endl;
    }
};
void show(Animal *p){
    p->Report();
}
int main(){
    Tiger tiger;
    Monkey monkey;
    Animal animal = tiger;
    show(&tiger);
    show(&monkey);
    show(&animal);
    return 0;
}
运行结果:
Report from Tiger!
Report from Monkey!
Report from Animal!
[Finished in 0.3s]
#include <iostream>
using namespace std;
class Base{
private:
    int base;
public:
    Base(int b){
        base = b;
        cout<<"base = "<<b<<endl;
    }
    ~Base(){}
};
class Derived: public Base{ //按照base->derived的顺序赋值
private:
    Base bb;
    int derived;
public:
    Derived(int d, int b, int c):bb(c),Base(b){
        derived = d;
        cout<<"derived = "<<derived<<endl;
    }
    ~Derived(){}
};
int main(){
    Derived d(3,4,5);
    return 0;
}
运行结果:
base = 4
base = 5
derived = 3
[Finished in 0.3s]
#include <iostream> 
using namespace std; 
class Base{
public:
    Base (int i,int j){ x0=i; y0=j;}
    void Move(int x,int y){ x0+=x; y0+=y;}
    void Show(){ cout<<"Base("<<x0<<","<<y0<<")"<<endl;}
private:
    int x0,y0;
};
class Derived: private Base{ 
public:
    Derived(int i,int j,int m,int n):Base(i,j){ x=m; y=n;}
    void Show (){cout<<"Next("<<x<<","<<y<<")"<<endl;} 
    void Move1(){Move(2,3);}
    void Show1(){Base::Show();}
private: 
    int x,y;
};
int main( ){
    Base b(1,2); 
    b.Show();
    Derived d(3,4,10,15); 
    d.Move1(); 
    d.Show();
    d.Show1();
    return 0;
}
Base(1,2)
Next(10,15)
Base(5,7)
[Finished in 0.3s]
#include <iostream> 
#include <string> 
#include <vector> 
using namespace std; 
class Sales{
private:
    string product;
    double price;
    double quantity; 
public:
    Sales(string prod,double p,double q):product(prod),price(p),quantity(q){}
    virtual double net_price()const{return price*quantity;} 
};
class DiscountSales:public Sales{ 
private:
    double rate; 
public:
    DiscountSales(string prod,double p,double q,double r) :Sales(prod,p,q),rate(r){}
virtual double net_price()const{return Sales::net_price()*rate;} 
};
class FullDiscountSales:public Sales{ 
private:
    double fullMoney,discountMoney; 
public:
    FullDiscountSales(string prod,double p,double q,double f,double d) :Sales(prod,p,q),fullMoney(f),discountMoney(d){}
    virtual double net_price()const{
        double money=Sales::net_price();
        int count=0;
        while((money-=fullMoney)>=0) {count++;} 
        return Sales::net_price()-count*discountMoney;
    } 
};
int main(){
    vector< Sales* > vec;
    vec.push_back(new DiscountSales("C++",100,2,0.8)); 
    vec.push_back(new FullDiscountSales("Java",80,5,200,30)); 
    cout<<vec[0]->net_price()<<endl; 
    cout<<vec[1]->net_price()<<endl;
    double totalPrice=0;
    for(auto p : vec) totalPrice+=p->net_price(); 
        cout<<"totalPrice:"<<totalPrice<<endl;
    for(auto p: vec) delete p;
return 0;
}
运行结果:
160
340
totalPrice:500
[Finished in 0.4s]
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容

  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy阅读 9,516评论 1 51
  • C++文件 例:从文件income. in中读入收入直到文件结束,并将收入和税金输出到文件tax. out。 检查...
    SeanC52111阅读 2,776评论 0 3
  • 伊坂幸太郎:一想到人类居然不用考试就能为人父母,真是太可怕了! 在每一个父母心中都有过孩子不听话的片段,或者你正在...
    三十七度半1号阅读 495评论 1 0
  • mac更新系统自带的svn,哎, 这边公司居然没用git。 svn 安装 一行代码homebrew在终端下输入命令...
    nothingwxq阅读 313评论 0 0
  • 下午放学去接悠悠时碰到了小嫂,她跟我说起早上侄儿回家时特别开心,说是碰到了我,而且我表扬了他。 在侄儿眼里,小姑可...
    老草阅读 343评论 10 7