c++ primer plus第六版第十三章编程练习

  1. 根据声明编写派生类classic,添加char成员(存储CD中主要作品的字符串),并修改声明使得基类成员函数为虚,并且如果某个方法不需要,删除掉。
    题目类声明
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&c);
    Cd();
    ~Cd();
    void report()const;
    Cd &operator=(const Cd&c);
};

题目要求的测试程序

#include <iostream>
#include "cd.h"
using namespace std;
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:" << endl;
    c1.report();
    c2.report();
    cout << endl;

    cout << "Using type cd * pointer to objects:" << endl;
    pcd->report();
    pcd = &c2;
    pcd->report();
    cout << endl;

    cout << "Calling a function with a Cd reference argument:" << endl;
    Bravo(c1);
    Bravo(c2);
    cout << endl;

    cout << "Testing assignment:" << endl;
    classic copy;
    copy = c2;
    copy.report();
    system("pause");
    return 0;
}
void Bravo(const Cd &disk) { disk.report(); }

完善后的类声明

//base class
class Cd
{
private:
    char performers[50];
    char label[20];
    int selections;
    double playtime;

public:
    Cd(const char *s1 = "nobody", const char *s2 = "null", int n = 0, double x = 0.0);
    Cd(const Cd &c); //copy constructor
    virtual ~Cd() {}
    virtual void report() const;
    virtual Cd &operator=(const Cd &c);
};
//derived class
class classic : public Cd
{
private:
    char work[20];

public:
    classic(const char *s1 = "nobody", const char *s2 = "null", const char *c = "null", int s = 0, double p = 0.0);
    classic(const Cd &c, const char *w);
    virtual void report() const;
    virtual classic &operator=(const classic &c);
};

方法实现

#include <iostream>
#include "cd.h"
#include <cstring>
//Cd methods
Cd::Cd(const char *s1, const char *s2, int n, double x)
{
    strcpy(performers, s1);
    strcpy(label, s2);
    selections = n;
    playtime = x;
}
Cd::Cd(const Cd &c)
{
    strcpy(performers, c.performers);
    strcpy(label, c.label);
    selections = c.selections;
    playtime = c.playtime;
} //copy constructor
void Cd::report() const
{
    std::cout << "Performers: " << performers << "\n";
    std::cout << "label: " << label << " number of selections:" << selections << std::endl;
    std::cout << "playing time in minutes: " << playtime << std::endl;
}
Cd &Cd::operator=(const Cd &c)
{
    if (this == &c)
        return *this;
    strcpy(performers, c.performers);
    strcpy(label, c.label);
    selections = c.selections;
    playtime = c.playtime;
    return *this;
}
//classic methods
classic::classic(const char *s1, const char *s2, const char *c, int s, double p) : Cd(s1, s2, s, p)
{
    strcpy(work, c);
}
classic::classic(const Cd &c, const char *w) : Cd(c)
{
    strcpy(work, w);
}
void classic::report() const
{
    Cd::report();
    std::cout << "Main work in CD: " << work << std::endl;
}
classic &classic::operator=(const classic &c)
{
    if (this == &c)
        return *this;
    Cd::operator=(c);
    strcpy(work, c.work);
    return *this;
}

在这里插入图片描述

  1. 在练习一的基础上进行改动,让两个类以动态内存分配来记录字符串。由于派生类和基类都使用new来动态分配内存,则派生类的析构函数、复制构造函数和赋值运算符函数就不能使用默认函数了,应该重新声明定义。
    类声明
//base class
class Cd
{
private:
    char *performers;
    char *label;
    int selections;
    double playtime;

public:
    Cd(const char *s1 = "nobody", const char *s2 = "null", int n = 0, double x = 0.0);
    Cd(const Cd &c); //copy constructor
    virtual ~Cd();
    virtual void report() const;
    virtual Cd &operator=(const Cd &c);
};
//derived class
class classic : public Cd
{
private:
    char *work;

public:
    classic(const char *s1 = "nobody", const char *s2 = "null", const char *c = "null", int s = 0, double p = 0.0);
    classic(const Cd &c, const char *w);
    classic(const classic &c);
    ~classic();
    virtual void report() const;
    virtual classic &operator=(const classic &c);
};

方法实现声明

#include <iostream>
#include "cd.h"
#include <cstring>
//Cd methods
Cd::Cd(const char *s1, const char *s2, int n, double x)
{
    performers = new char[strlen(s1) + 1];
    strcpy(performers, s1);
    label = new char[strlen(s2) + 1];
    strcpy(label, s2);
    selections = n;
    playtime = x;
}
Cd::Cd(const Cd &c)
{
    performers = new char[strlen(c.performers) + 1];
    label = new char[strlen(c.label) + 1];
    strcpy(performers, c.performers);
    strcpy(label, c.label);
    selections = c.selections;
    playtime = c.playtime;
} //copy constructor
Cd::~Cd()
{
    delete[] performers;
    delete[] label;
}
void Cd::report() const
{
    std::cout << "Performers: " << performers << "\n";
    std::cout << "label: " << label << "\nnumber of selections:" << selections << std::endl;
    std::cout << "playing time in minutes: " << playtime << std::endl;
}
Cd &Cd::operator=(const Cd &c)
{
    if (this == &c)
        return *this;
    delete[] performers;
    performers = new char[strlen(c.performers) + 1];
    delete[] label;
    label = new char[strlen(c.label) + 1];
    strcpy(performers, c.performers);
    strcpy(label, c.label);
    selections = c.selections;
    playtime = c.playtime;
    return *this;
}
//classic methods
classic::classic(const char *s1, const char *s2, const char *c, int s, double p) : Cd(s1, s2, s, p)
{
    work = new char[strlen(c) + 1];
    strcpy(work, c);
}
classic::classic(const Cd &c, const char *w) : Cd(c)
{
    work = new char[strlen(w) + 1];
    strcpy(work, w);
}
classic::classic(const classic &c) : Cd(c)
{
    work = new char[strlen(c.work) + 1];
    strcpy(work, c.work);
}
classic::~classic()
{
    delete[] work;
}
void classic::report() const
{
    Cd::report();
    std::cout << "Main work in CD: " << work << std::endl;
}
classic &classic::operator=(const classic &c)
{
    if (this == &c)
        return *this;
    Cd::operator=(c);
    delete[] work;
    work = new char[strlen(c.work) + 1];
    strcpy(work, c.work);
    return *this;
}

一样的测试程序,一样的测试结果,为了验证,还是展示一下吧
在这里插入图片描述

  1. 修改抽象基类例子中的三个类,使其从一个ABC派生出来,并使用书本的测试程序进行测试。
    类声明头文件
#include <iostream>
//base ABC class
class ABC
{
public:
    ABC() {}
    virtual ~ABC() {}
    virtual void view() const = 0;
};
//derived class baseDMA
class baseDMA : public ABC
{
private:
    char *label;
    int rating;

public:
    baseDMA(const char *l = "null", int r = 0);
    baseDMA(const baseDMA &bs);
    ~baseDMA();
    baseDMA &operator=(const baseDMA &bs);
    friend std::ostream &operator<<(std::ostream &os, const baseDMA &bs);
    virtual void view() const;
};
//derived class lacksDMA
class lacksDMA : public baseDMA
{
private:
    enum
    {
        COL_LEN = 40
    };
    char color[COL_LEN];

public:
    lacksDMA(const baseDMA &bs, const char *c);
    lacksDMA(const char *c = "blank", const char *l = "null", int r = 0);
    friend std::ostream &operator<<(std::ostream &os, const lacksDMA &ls);
    virtual void view() const;
};
//derived class hasDMA
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 &bs);
    hasDMA(const hasDMA &hs);
    ~hasDMA();
    hasDMA &operator=(const hasDMA &hs);
    friend std::ostream &operator<<(std::ostream &os, const hasDMA &hs);
    virtual void view() const;
};

方法实现

#include "ABC.h"
#include <cstring>
//baseDMa methods
baseDMA::baseDMA(const char *l, int r)
{
    label = new char[strlen(l) + 1];
    strcpy(label, l);
    rating = r;
}
baseDMA::baseDMA(const baseDMA &bs)
{
    delete[] label;
    label = new char[strlen(bs.label) + 1];
    strcpy(label, bs.label);
    rating = bs.rating;
}
baseDMA::~baseDMA()
{
    delete[] label;
}
baseDMA &baseDMA::operator=(const baseDMA &bs)
{
    if (this == &bs)
        return *this;
    delete[] label;
    label = new char[strlen(bs.label) + 1];
    strcpy(label, bs.label);
    rating = bs.rating;
    return *this;
}
std::ostream &operator<<(std::ostream &os, const baseDMA &bs)
{
    os << "Label: " << bs.label << " rating: " << bs.rating;
    return os;
}
void baseDMA::view() const
{
    std::cout << "Label: " << label << " rating: " << rating;
}
//lacksDMA methods
lacksDMA::lacksDMA(const baseDMA &bs, const char *c) : baseDMA(bs)
{
    strcpy(color, c);
}
lacksDMA::lacksDMA(const char *c, const char *l, int r) : baseDMA(l, r)
{
    strcpy(color, l);
}
std::ostream &operator<<(std::ostream &os, const lacksDMA &ls)
{
    os << "color: " << ls.color;
    return os;
}
void lacksDMA::view() const
{
    baseDMA::view();
    std::cout << "color: " << color << std::endl;
}
//hasDMA methods
hasDMA::hasDMA(const char *s, const char *l, int r) : baseDMA(l, r)
{
    style = new char[strlen(s) + 1];
    strcpy(style, s);
}
hasDMA::hasDMA(const char *s, const baseDMA &bs) : baseDMA(bs)
{
    style = new char[strlen(s) + 1];
    strcpy(style, s);
}
hasDMA::hasDMA(const hasDMA &hs)
{
    delete[] style;
    style = new char[strlen(hs.style) + 1];
    strcpy(style, hs.style);
}
hasDMA::~hasDMA()
{
    delete[] style;
}
hasDMA &hasDMA::operator=(const hasDMA &hs)
{
    if (this == &hs)
        return *this;
    delete[] style;
    style = new char[strlen(hs.style) + 1];
    strcpy(style, hs.style);
}
std::ostream &operator<<(std::ostream &os, const hasDMA &hs)
{
    os << "style: " << hs.style;
    return os;
}
void hasDMA::view() const
{
    baseDMA::view();
    std::cout << "style: " << style << std::endl;
}

测试程序

#include <iostream>
#include <string>
#include "ABC.h"
using namespace std;
const int CLIENTS = 4;
const int Max = 20;
int main()
{
    using std::cin;
    using std::cout;
    using std::endl;
    ABC *p[CLIENTS];
    string temp;
    int tempnum;
    string stemp;
    string ctemp;
    char kind;
    for (int i = 0; i < CLIENTS; i++)
    {
        cout << "Enter the label: ";
        getline(cin, temp);
        cout << "Enter the rating: ";
        cin >> tempnum;
        cout << "Enter 1 for baseDMA or "
             << "2 for lacksDMA "
             << "3 for hasDMA:";
        while (cin >> kind && (kind != '1' && kind != '2' && kind != '3'))
            cout << "Enter either 1 or 2: ";
        while (cin.get() != '\n')
            continue;
        if (kind == '1')
            p[i] = new baseDMA(temp.c_str(), tempnum);
        else if (kind == '2')
        {
            cout << "Enter the color: ";
            getline(cin, ctemp);
            p[i] = new lacksDMA(ctemp.c_str(), temp.c_str(), tempnum);
        }
        else
        {
            cout << "Enter the style: ";
            getline(cin, stemp);
            p[i] = new hasDMA(stemp.c_str(), temp.c_str(), tempnum);
        }
    }
    cout << endl;
    for (int j = 0; j < CLIENTS; j++)
        p[j]->view();
    for (int k = 0; k < CLIENTS; k++)
        delete p[k];
    system("pause");
    return 0;
}

总结:能用string就用string,程序能运行但卡住就一定是换行符卡在了输入流里。结果就不显示了,阿婆主心力交瘁了。
4. 完善port类和vintageport类

#include <iostream>
using namespace std;
//base class
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); //add b to bottles
    Port &operator-=(int b); //subtracts b from bottles
    int bottlecount() const { return bottles; }
    virtual void show() const;
    friend ostream &operator<<(ostream &os, const Port &p);
};
//derived class
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);
    virtual void show() const;
    friend ostream &operator<<(ostream &os, const VintagePort &vp);
};

方法实现文件

#include "bop.h"
#include <cstring>
//Port methods
Port::Port(const char *br, const char *st, int b)
{
    brand = new char[strlen(br) + 1];
    strcpy(brand, br);
    strcpy(style, st);
    bottles = b;
}
Port::Port(const Port &p)
{
    delete[] brand;
    brand = new char[strlen(p.brand) + 1];
    strcpy(brand, p.brand);
    strcpy(style, p.style);
    bottles = p.bottles;
}
Port &Port::operator=(const Port &p)
{
    if (this == &p)
        return *this;
    delete[] brand;
    brand = new char[strlen(p.brand) + 1];
    strcpy(brand, p.brand);
    strcpy(style, p.style);
    bottles = p.bottles;
    return *this;
}
Port &Port::operator+=(int b)
{
    bottles += b;
    return *this;
} //add b to bottles
Port &Port::operator-=(int b)
{
    if (bottles >= b)
        bottles -= b;
    return *this;
} //subtracts b from bottles
void Port::show() const
{
    std::cout << "Brand: " << brand << std::endl;
    std::cout << "Kind: " << style << std::endl;
    std::cout << "Bottles: " << bottles << std::endl;
}
ostream &operator<<(ostream &os, const Port &p)
{
    os << p.brand << "," << p.style << ", " << p.bottles;
    return os;
}
//VintagePort methods
VintagePort::VintagePort()
{
    strcpy(nickname, "vintage");
    year = 0;
}
VintagePort::VintagePort(const char *br, int b, const char *nn, int y) : Port(br, "vintage", b)
{
    nickname = new char[strlen(nn) + 1];
    strcpy(nickname, nn);
    year = y;
}
VintagePort::VintagePort(const VintagePort &vp) : Port(vp)
{
    delete[] nickname;
    nickname = new char[strlen(vp.nickname) + 1];
    strcpy(nickname, vp.nickname);
    year = vp.year;
}
VintagePort &VintagePort::operator=(const VintagePort &vp)
{
    if (this == &vp)
        return *this;
    delete[] nickname;
    nickname = new char[strlen(vp.nickname) + 1];
    strcpy(nickname, vp.nickname);
    year = vp.year;
    return *this;
}
void VintagePort::show() const
{
    Port::show();
    std::cout << "Nickname: " << nickname << std::endl;
    std::cout << "Year: " << year << std::endl;
}
ostream &operator<<(ostream &os, const VintagePort &vp)
{
    os << Port(vp);
    os << " ," << vp.nickname << ", " << vp.year;
    return os;
}

测试程序

#include <iostream>
#include "bop.h"
using namespace std;
int main()
{
    {
        Port port1("Gallo", "tawny", 20);
        VintagePort vp("ooooo", 20, "The Noble", 1997);
        port1.show();
        vp.show();
        cout << endl;

        VintagePort vp2 = vp;
        Port port2 = port1;
        cout << vp2 << endl;
        cout << port2 << endl;
        system("pause");
        return 0;
    }
}

在这里插入图片描述
观察测试程序可以看到,我在主运行外面又加了一个大括号,具体原因我也没明白过来,不过可以猜想是析构函数的锅,看过c++ primer plus的都知道,在讲解析构函数的章节中有过这种做法的出现就是程序清单10.6,要确认我的想法就是在析构函数中加上一些启示语句,然后删减大括号进行对比测试即可,这里我就不测试了,大家如果有不同意见,欢迎交流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值