《C++ Primer Plus(第六版)》(27)(第十三章 类继承 编程题答案)

来源:互联网 发布:php微信二次开发教程 编辑:程序博客网 时间:2024/05/18 18:02

13.11 编程练习


1.以下面的类声明为基础:

class Cd{private:char performers[50];char label[20];int selections;double playtime;public:Cd(char * s1, char* s2, int n, double x);Cd(const Cd& d);Cd();~Cd();void Report() const;Cd& operator=(const Cd& d);};
派生出一个Classic类,并添加一组char成员,用于存储指出CD中主要作品的字符串。修改上述声明,使基类的所有函数都是虚的。如果上述定义声明的某个方法并不需要,则请删除它。使用下面的程序测试您的产品:

////  main.cpp//  HelloWorld////  Created by feiyin001 on 16/12/21.//  Copyright (c) 2016年 FableGame. All rights reserved.//#include <iostream>#include "Test.h"using namespace std;using namespace FableGame;void Bravo(const Cd& disk);int main(){    Cd c1("Beatles", "Capitol", 14, 35.5);    Classic c2 = Classic("Piano Sonata in B flat, Fantasia in C",                         "Alfred Brendel", "Philips", 2, 57.17);    Cd* pcd = & c1;    cout << "Using object directly:\n";    c1.Report();    c2.Report();        cout << "Using type cd * pointer to Objects:\n";    pcd->Report();    pcd = & c2;    pcd->Report();        cout << "Calling a function with a Cd reference argument:\n";    Bravo(c1);    Bravo(c2);        cout << "Testing assignment: ";    Classic copy;    copy = c2;    copy.Report();    return 0;}void Bravo(const Cd & disk){    disk.Report();}


修改:

Test.h

////  Test.h//  HelloWorld////  Created by feiyin001 on 16/12/21.//  Copyright (c) 2016年 FableGame. All rights reserved.//#ifndef _Test_H_#define _Test_H_#include <iostream>using namespace std;namespace FableGame{        class Cd    {    private:        char performers[50];//表演者        char label[20];//标签        int selections;        double playtime;    public:        Cd(char * s1, char* s2, int n, double x);        Cd();        ~Cd();        void Report() const;    };    class Classic : public Cd    {    private:        char info[80];    public:        Classic(char * s1, char* s2, char* s3, int n, double x);        Classic();        void Report() const;    };}#endif
Test.cpp
////  Test.cpp//  HelloWorld////  Created by feiyin001 on 16/12/21.//  Copyright (c) 2016年 FableGame. All rights reserved.//#include "Test.h"#include <iostream>#include <cstdlib>using namespace std;using namespace FableGame;Cd::Cd(char * s1, char* s2, int n, double x){    strcpy(performers, s1);    strcpy(label, s2);    selections = n;    playtime = x;}Cd::Cd(){    performers[0] = '\0';    label[0] = '\0';    selections = 0;    playtime = 0;}Cd::~Cd(){    }void Cd::Report()const{    cout << "performers:" << performers << " label:" << label << endl;    cout << "selections:" << selections << " playtime:" << playtime << endl;}Classic::Classic(char * s1, char* s2, char* s3, int n, double x): Cd(s2, s3, n, x){    strcpy(info, s1);}Classic::Classic():Cd(){    info[0] = '\0';}void Classic::Report() const{    Cd::Report();    cout << "info" << info << endl;}
main.cpp

////  main.cpp//  HelloWorld////  Created by feiyin001 on 16/12/21.//  Copyright (c) 2016年 FableGame. All rights reserved.//#include <iostream>#include "Test.h"using namespace std;using namespace FableGame;void Bravo(const Cd& disk);int main(){    Cd c1("Beatles", "Capitol", 14, 35.5);    Classic c2 = Classic("Piano Sonata in B flat, Fantasia in C",                         "Alfred Brendel", "Philips", 2, 57.17);    Cd* pcd = & c1;    cout << "Using object directly:\n";    c1.Report();    c2.Report();        cout << "Using type cd * pointer to Objects:\n";    pcd->Report();    pcd = & c2;    pcd->Report();        cout << "Calling a function with a Cd reference argument:\n";    Bravo(c1);    Bravo(c2);        cout << "Testing assignment: ";    Classic copy;    copy = c2;    copy.Report();    return 0;}void Bravo(const Cd & disk){    disk.Report();}
类成员不用指针,果然方便很多

2.完成练习1,但让两个类使用动态内存分配而不是长度固定的数组来记录字符串。

Test.h

////  Test.h//  HelloWorld////  Created by feiyin001 on 16/12/21.//  Copyright (c) 2016年 FableGame. All rights reserved.//#ifndef _Test_H_#define _Test_H_#include <iostream>using namespace std;namespace FableGame{        class Cd    {    private:        char* performers;//表演者        char* label;//标签        int selections;        double playtime;    public:        Cd(char * s1, char* s2, int n, double x);        Cd(const Cd& d);        Cd();        ~Cd();        void Report() const;        Cd & operator=(const Cd& d);    };    class Classic : public Cd    {    private:        char* info;    public:        Classic(char * s1, char* s2, char* s3, int n, double x);        Classic(const Classic& c);        Classic();        void Report() const;        Classic & operator=(const Classic& c);    };}#endif
Test.cpp

////  Test.cpp//  HelloWorld////  Created by feiyin001 on 16/12/21.//  Copyright (c) 2016年 FableGame. All rights reserved.//#include "Test.h"#include <iostream>#include <cstdlib>using namespace std;using namespace FableGame;Cd::Cd(char * s1, char* s2, int n, double x){    performers = new char[strlen(s1) + 1];    label = new char[strlen(s2) + 1];    strcpy(performers, s1);    strcpy(label, s2);    selections = n;    playtime = x;}Cd::Cd(const Cd& d){    performers = new char[strlen(d.performers) + 1];    label = new char[strlen(d.label) + 1];    strcpy(performers, d.performers);    strcpy(label, d.label);    selections = d.selections;    playtime = d.playtime;}Cd::Cd(){    performers = new char[1];    label = new char[1];    performers[0] = '\0';    label[0] = '\0';    selections = 0;    playtime = 0;}Cd::~Cd(){    delete [] performers;    delete [] label;}void Cd::Report()const{    cout << "performers:" << performers << " label:" << label << endl;    cout << "selections:" << selections << " playtime:" << playtime << endl;}Cd & Cd::operator=(const Cd& d){    if (this == &d) {        return *this;    }    delete [] performers;    delete [] label;    performers = new char[strlen(d.performers) + 1];    label = new char[strlen(d.label) + 1];    strcpy(performers, d.performers);    strcpy(label, d.label);    selections = d.selections;    playtime = d.playtime;    return *this;}Classic::Classic(char * s1, char* s2, char* s3, int n, double x): Cd(s2, s3, n, x){    info = new char[strlen(s1) + 1];    strcpy(info, s1);}Classic::Classic(const Classic& c):Cd(c){    info = new char[strlen(c.info) + 1];    strcpy(info, c.info);}Classic::Classic():Cd(){    info = new char[1];    info[0] = '\0';}void Classic::Report() const{    Cd::Report();    cout << "info" << info << endl;}Classic & Classic::operator=(const Classic& c){    if (this == & c) {        return *this;    }    Cd::operator=(c);    delete [] info;    info = new char[strlen(c.info) + 1];    strcpy(info, c.info);    return *this;}

3.修改baseDMA-lacksDMA-hasDMA类层次,让三个类都从一个ABC派生而来,然后使用让程序清单13.10相似的程序对结果进行测试。也就是说,它应使用ABC指针数组,并让用户决定要创建的对象类型。在类定义中添加virtual View()方法以处理数据显示。

看看原来的代码:

Test.h

////  Test.h//  HelloWorld////  Created by feiyin001 on 16/12/21.//  Copyright (c) 2016年 FableGame. All rights reserved.//#ifndef _Test_H_#define _Test_H_#include <iostream>using namespace std;namespace FableGame{class baseDMA{private:char* label;int rating;public:baseDMA(const char* l = "null", int r = 0);baseDMA(const baseDMA& rs);virtual ~baseDMA();baseDMA& operator=(const baseDMA& rs);friend std::ostream& operator<<(std::ostream& os, const baseDMA& rs);};class lacksDMA:public baseDMA{private:enum{COL_LEN = 40};char color[COL_LEN];public:lacksDMA(const char* c = "blank", const char* l = "null", int r = 0);lacksDMA(const char* c, const baseDMA& ls);friend std::ostream& operator<<(std::ostream& os, const lacksDMA& ls);}; class hasDMA : public baseDMA{private:char * style;public:hasDMA(const char* s = "none", const char* l = "null", int r = 0);hasDMA(const char* s, const baseDMA& hs);hasDMA(const hasDMA& hs);~hasDMA();hasDMA& operator=(const hasDMA& hs);friend std::ostream& operator<<(std::ostream& os, const hasDMA& hs);};}#endif
Test.cpp

////  Test.cpp//  HelloWorld////  Created by feiyin001 on 16/12/21.//  Copyright (c) 2016年 FableGame. All rights reserved.//#include "Test.h"#include <iostream>#include <cstdlib>using namespace std;using namespace FableGame;FableGame::baseDMA::baseDMA(const char* l /*= "null"*/, int r /*= 0*/){int size = strlen(l) + 1;label = new char[size];strcpy_s(label, size, l );rating = r;}FableGame::baseDMA::baseDMA(const baseDMA& rs){int size = strlen(rs.label) + 1;label = new char[size];strcpy_s(label, size, rs.label);rating = rs.rating;}FableGame::baseDMA::~baseDMA(){delete[] label;}baseDMA& FableGame::baseDMA::operator=(const baseDMA& rs){if (this == &rs){return *this;}delete[] label;int size = strlen(rs.label) + 1;label = new char[size];strcpy_s(label, size, rs.label );rating = rs.rating;return *this;}std::ostream& FableGame::operator<<(std::ostream& os, const baseDMA& rs){os << "Label: " << rs.label << endl;os << "Rating: " << rs.rating << endl;return os;}FableGame::lacksDMA::lacksDMA(const char* c, const char* l, int r) : baseDMA(l, r){strncpy_s(color, c, 39);color[39] = '\0';}FableGame::lacksDMA::lacksDMA(const char* c, const baseDMA& rs) :baseDMA(rs){strncpy_s(color, c, COL_LEN - 1);color[COL_LEN - 1] = '\0';}std::ostream& FableGame::operator<<(std::ostream& os, const lacksDMA& ls){os << (const baseDMA&)ls;os << "Color: " << ls.color << endl;return os;}FableGame::hasDMA::hasDMA(const char* s, const char* l, int r) :baseDMA(l, r){style = new char[strlen(s) + 1];strcpy_s(style, strlen(s) + 1, s);}FableGame::hasDMA::hasDMA(const char* s, const baseDMA& rs) :baseDMA(rs){style = new char[strlen(s) + 1];strcpy_s(style, strlen(s) + 1, s);}FableGame::hasDMA::hasDMA(const hasDMA& hs) :baseDMA(hs){style = new char[strlen(hs.style) + 1];strcpy_s(style, strlen(hs.style) + 1, hs.style);}FableGame::hasDMA::~hasDMA(){delete[] style;}hasDMA& FableGame::hasDMA::operator=(const hasDMA& hs){if (this == &hs){return *this;}baseDMA::operator=(hs);delete[] style;style = new char[strlen(hs.style) + 1];strcpy_s(style, strlen(hs.style) + 1, hs.style);return *this;}std::ostream& FableGame::operator<<(std::ostream& os, const hasDMA& hs){os << (const baseDMA&)hs;os << "Style: " << hs.style << endl;return os;}
修改后的:

Test.h

////  Test.h//  HelloWorld////  Created by feiyin001 on 16/12/21.//  Copyright (c) 2016年 FableGame. All rights reserved.//#ifndef _Test_H_#define _Test_H_#include <iostream>using namespace std;namespace FableGame{class ABC{private:char* label;int rating;public:ABC(const char* l = "null", int r = 0);ABC(const ABC& rs);virtual ~ABC();ABC& operator=(const ABC& rs);friend std::ostream& operator<<(std::ostream& os, const ABC& rs);virtual void view() = 0;char* getLabel(){ return label; }int getRating(){ return rating; }};class baseDMA :public ABC{public:baseDMA(const char* l = "null", int r = 0);baseDMA(const baseDMA& rs);virtual void view();};class lacksDMA :public ABC{private:enum{COL_LEN = 40};char color[COL_LEN];public:lacksDMA(const char* c = "blank", const char* l = "null", int r = 0);lacksDMA(const char* c, const ABC& ls);friend std::ostream& operator<<(std::ostream& os, const lacksDMA& ls);virtual void view();}; class hasDMA : public ABC{private:char * style;public:hasDMA(const char* s = "none", const char* l = "null", int r = 0);hasDMA(const char* s, const ABC& hs);hasDMA(const hasDMA& hs);~hasDMA();hasDMA& operator=(const hasDMA& hs);friend std::ostream& operator<<(std::ostream& os, const hasDMA& hs);virtual void view();};}#endif
Test.cpp

////  Test.cpp//  HelloWorld////  Created by feiyin001 on 16/12/21.//  Copyright (c) 2016年 FableGame. All rights reserved.//#include "Test.h"#include <iostream>#include <cstdlib>using namespace std;using namespace FableGame;FableGame::ABC::ABC(const char* l /*= "null"*/, int r /*= 0*/){int size = strlen(l) + 1;label = new char[size];strcpy_s(label, size, l );rating = r;}FableGame::ABC::ABC(const ABC& rs){int size = strlen(rs.label) + 1;label = new char[size];strcpy_s(label, size, rs.label);rating = rs.rating;}FableGame::ABC::~ABC(){delete[] label;}ABC& FableGame::ABC::operator=(const ABC& rs){if (this == &rs){return *this;}delete[] label;int size = strlen(rs.label) + 1;label = new char[size];strcpy_s(label, size, rs.label );rating = rs.rating;return *this;}void FableGame::ABC::view(){cout << "Label: " << getLabel() << endl;cout << "Rating: " << getRating() << endl;}std::ostream& FableGame::operator<<(std::ostream& os, const ABC& rs){os << "Label: " << rs.label << endl;os << "Rating: " << rs.rating << endl;return os;}FableGame::lacksDMA::lacksDMA(const char* c, const char* l, int r) : ABC(l, r){strncpy_s(color, c, 39);color[39] = '\0';}FableGame::lacksDMA::lacksDMA(const char* c, const ABC& rs) :ABC(rs){strncpy_s(color, c, COL_LEN - 1);color[COL_LEN - 1] = '\0';}void FableGame::lacksDMA::view(){ABC::view();cout << "Color: " << color << endl;}std::ostream& FableGame::operator<<(std::ostream& os, const lacksDMA& ls){os << (const ABC&)ls;os << "Color: " << ls.color << endl;return os;}FableGame::hasDMA::hasDMA(const char* s, const char* l, int r) :ABC(l, r){style = new char[strlen(s) + 1];strcpy_s(style, strlen(s) + 1, s);}FableGame::hasDMA::hasDMA(const char* s, const ABC& rs) :ABC(rs){style = new char[strlen(s) + 1];strcpy_s(style, strlen(s) + 1, s);}FableGame::hasDMA::hasDMA(const hasDMA& hs) :ABC(hs){style = new char[strlen(hs.style) + 1];strcpy_s(style, strlen(hs.style) + 1, hs.style);}FableGame::hasDMA::~hasDMA(){delete[] style;}hasDMA& FableGame::hasDMA::operator=(const hasDMA& hs){if (this == &hs){return *this;}ABC::operator=(hs);delete[] style;style = new char[strlen(hs.style) + 1];strcpy_s(style, strlen(hs.style) + 1, hs.style);return *this;}void FableGame::hasDMA::view(){ABC::view();cout << "Style: " << style << endl;}std::ostream& FableGame::operator<<(std::ostream& os, const hasDMA& hs){os << (const ABC&)hs;os << "Style: " << hs.style << endl;return os;}FableGame::baseDMA::baseDMA(const char* l /*= "null"*/, int r /*= 0*/) :ABC(l, r){}FableGame::baseDMA::baseDMA(const baseDMA& rs) : ABC(rs){}void FableGame::baseDMA::view(){ABC::view();}
main.cpp

#include <iostream>     #include "Test.h"#include <string>using namespace std;using namespace FableGame;const int ARR_SIZE = 3;int main(int argc, const char * argv[]){ABC* p_ABC[ARR_SIZE];char temp[40];int tempnum;int kind;for (int i = 0; i < ARR_SIZE; i ++){cout << "Enter label: ";cin.getline( temp, 40);cout << "Enter Rating: ";cin >> tempnum;cout << "Enter 1 for baseDMA or 2 for lacksDMA or 3 for hasDMA: ";while (cin >> kind && (kind != 1 && kind != 2 && kind != 3)){cout << "Enter either 1 or 2 or 3: ";}cin.get();if (kind == 1){p_ABC[i] = new baseDMA(temp, tempnum);}else if (kind == 2){char color[40];cout << "Enter the color: ";cin.getline(color, 40);p_ABC[i] = new lacksDMA(color, temp, tempnum);}else if (kind == 3){char style[40];cout << "Enter the style: ";cin.getline(style, 40);p_ABC[i] = new hasDMA(style, temp, tempnum);} }cout << endl;for (int i = 0; i < ARR_SIZE; i ++){p_ABC[i]->view();cout << endl;}for (int i = 0; i < ARR_SIZE; i ++){delete p_ABC[i];}cout << "Done." <<endl;return 0;} 
虚基类其实跟普通的基类差不多,只是把baseDMA改名ABC,加一个纯虚函数,然后再新建一个ABC就行了。

不过对于getline不是很熟。

4.Benevolent Order of Programmers 用来维护瓶装葡萄酒箱。为描述它,BOP Portmaster设置了一个Port类,其声明如下:

    class Port    {    private:        char* brand;        char style[20];        int bottles;    public:        Port(const char* br = "none", const char* st = "none", int b = 0);        Port(const Port& p);        virtual ~Port(){ delete [] brand; }        Port& operator=(const Port& p);        Port& operator+=(int b);        Port& operator-=(int b);                int BottleCount()const { return bottles;}        virtual void Show()const;        friend ostream& operator<<(ostream& os, const Port& p);    };
show()方法按下面的格式显示信息:

Brand: Gallo

Kind: tawny

Bottles: 20

operator<<()函数按下面的格式显示信息(末尾没有换行符):

Gallo, tawny, 20

PortMaster完成了Port类的方法定义后派生了VintagePort类,然后被解职--因为不小心将一瓶45°Cockburn泼到了正在准备烤肉调料的人身上,VintagePort类如下所示:

    class VintagePort: public Port    {    private:        char* nickname;        int year;    public:        VintagePort();        VintagePort(const char* br, int b, const char* nn, int y);        VintagePort(const VintagePort& vp);        ~VintagePort(){ delete [] nickname;}        VintagePort& operator=(const VintagePort& vp);        void show()const;        friend ostream& operator<<(ostream& os, const VintagePort& vp);    };
您被指定负责完成VintagePort。

a.第一个任务是重新创建Port方法定义,因为前任被开除时销毁了方法定义。

看代码

b.第二个任务是解释为什么有的方法重新定义了,而有些没有重新定义。

有些方法写在头文件作为内联函数,无需重新定义了。

c.第三个任务是解释为何没有将operator=()和operator<<()声明为虚的。

operator=()是不能继承的,因为不能将父类复制给子类。

operator<<()是友元函数,无法继承。

d.第四个任务是提供VintagePort中各个方法的定义。
看代码。。。


Test.h

////  Test.h//  HelloWorld////  Created by feiyin001 on 16/12/21.//  Copyright (c) 2016年 FableGame. All rights reserved.//#ifndef _Test_H_#define _Test_H_#include <iostream>using namespace std;namespace FableGame{class Port{private:char* brand;char style[20];int bottles;public:Port(const char* br = "none", const char* st = "none", int b = 0);Port(const Port& p);virtual ~Port(){ delete[] brand; }Port& operator=(const Port& p);Port& operator+=(int b);Port& operator-=(int b);int BottleCount()const { return bottles; }virtual void Show()const;friend ostream& operator<<(ostream& os, const Port& p);};class VintagePort : public Port{private:char* nickname;int year;public:VintagePort();VintagePort(const char* br, int b, const char* nn, int y);VintagePort(const VintagePort& vp);~VintagePort(){ delete[] nickname; }VintagePort& operator=(const VintagePort& vp);void show()const;friend ostream& operator<<(ostream& os, const VintagePort& vp);};}#endif
Test.cpp

////  Test.cpp//  HelloWorld////  Created by feiyin001 on 16/12/21.//  Copyright (c) 2016年 FableGame. All rights reserved.//#include "Test.h"#include <iostream>#include <cstdlib>using namespace std;using namespace FableGame;FableGame::Port::Port(const char* br /*= "none"*/, const char* st /*= "none"*/, int b /*= 0*/){brand = new char[strlen(br) + 1];strcpy_s(brand, strlen(br) + 1, br);strcpy_s(style, 20, st);bottles = b;}FableGame::Port::Port(const Port& p){brand = new char[strlen(p.brand) + 1];strcpy_s(brand, strlen(p.brand) + 1, p.brand);strcpy_s(style, 20, p.style);bottles = p.bottles;}Port& FableGame::Port::operator=(const Port& p){if (this == &p){return *this;}delete[] brand;brand = new char[strlen(p.brand) + 1];strcpy_s(brand, strlen(p.brand) + 1, p.brand);strcpy_s(style, 20, p.style);bottles = p.bottles;return *this;}Port& FableGame::Port::operator+=(int b){bottles += b;return *this;}Port& FableGame::Port::operator-=(int b){bottles -= b;return *this;}void FableGame::Port::Show() const{cout << "Brand: " << brand << endl;cout << "Kind : " << style << endl;cout << "Bottles : " << bottles << endl;}ostream& FableGame::operator<<(ostream& os, const Port& p){os << p.brand << ", " << p.style << ", " << p.bottles;return os;}FableGame::VintagePort::VintagePort() :Port(){}FableGame::VintagePort::VintagePort(const char* br, int b, const char* nn, int y) : Port(br, "", b){nickname = new char[strlen(nn) + 1];strcpy_s(nickname, strlen(nn) + 1, nn);year = y;}FableGame::VintagePort::VintagePort(const VintagePort& vp) :Port(vp){nickname = new char[strlen(vp.nickname) + 1];strcpy_s(nickname, strlen(vp.nickname) + 1, vp.nickname);year = vp.year;}VintagePort& FableGame::VintagePort::operator=(const VintagePort& vp){if (this == &vp){return *this;}Port::operator=(vp);delete[] nickname;nickname = new char[strlen(vp.nickname) + 1];strcpy_s(nickname, strlen(vp.nickname) + 1, vp.nickname);year = vp.year;return *this;}void FableGame::VintagePort::show() const{Port::Show();cout << "nickname: " << nickname << endl;cout << "year: " << year << endl;}ostream& FableGame::operator<<(ostream& os, const VintagePort& vp){os << (const Port&)vp;os << ", " << vp.nickname << ", " << vp.year;return os;}







1 0
原创粉丝点击