c++primer plus 第13章 编程题第2题

#pragma once
#ifndef CD_H_
#define CD_H_
//base class

class Cd
{
private:
    char * performers;
    char * label;
    int selection;    //number of selection
    double playtime;
public:
    Cd();
    Cd(const Cd & d);
    Cd(char * s1, char * s2, int n, double x);
    virtual ~Cd();
    virtual void Report() const;    //reports all cd data
    Cd & operator= (const Cd & d);
};
#endif // !CD_H_
#pragma once
CD.h
#pragma once
#ifndef CLASSIC_H_
#define CLASSIC_H_
#include"CD.h"

class Classic : public Cd
{
private:
    char * mainprod;
public:

    Classic();
    Classic(char * s1, char * s2, char * s3, int n, double x);
    Classic(const Classic & a);
    ~Classic();
    Classic & operator=(const Classic & a);
    void Report() const;
};

#endif // !CLASSIC_H_
classic.h
#include"classic.h"
#include<cstring>
#include<iostream>
using std::strcpy;
using std::strlen;
using std::cout;
using std::endl;
//base cd

Cd::Cd()
{
    performers = new char[1];
    performers[0] = '\0';
    label = new char[1];
    label[0] = '\0';    //构造函数保持统一格式对应析构函数
    selection = 0;
    playtime = 0.0;
}

Cd::Cd(const Cd & a)
{
    int len;
    len = strlen(a.performers);
    performers = new char[len + 1];
    strcpy(performers, a.performers);
    len = strlen(a.label);
    label = new char[len + 1];
    strcpy(label, a.label);
    selection = a.selection;
    playtime = a.playtime;
}

Cd & Cd::operator=(const Cd & a)
{
    //记住第一步要先delete掉以前的,节省内存
    delete[]performers;
    delete[]label;
    int len;
    len = strlen(a.performers);
    performers = new char[len + 1];
    strcpy(performers, a.performers);
    len = strlen(a.label);
    label = new char[len + 1];
    strcpy(label, a.label);
    selection = a.selection;
    playtime = a.playtime;
    return *this;
}

Cd::Cd(char * s1, char * s2, int n, double x)
{
    int len;
    len = strlen(s1);
    performers = new char[len + 1];    //记得要加一,strlen不算‘\0’
    strcpy(performers, s1);
    len = strlen(s2);
    label = new char[len + 1];
    strcpy(label, s2);
    selection = n;
    playtime = x;
}

Cd::~Cd()
{
    delete[]performers;
    delete[]label;
}

void Cd::Report() const
{
    cout << "performers: " << performers << endl;
    cout << " label: " << label << endl;
    cout << " selection: " << selection << endl;
    cout << " playtime: " << playtime << endl;
}

Classic::~Classic()
{
    //Cd::~Cd;//这句不用,写了报错,重复删除
    delete[]mainprod;//派生析构只用删除派生类里的新成员就好
}

Classic::Classic() : Cd()
{
    mainprod = new char[1];
    mainprod[0] = '\0';    //构造函数要统一型式以兼容析构函数
}

Classic::Classic(char * s1, char * s2, char * s3, int a, double x) : Cd(s1, s2, a, x)
{
    int len;
    len = strlen(s3);
    mainprod = new char[len + 1];
    strcpy(mainprod, s3);
}

Classic::Classic(const Classic & a) : Cd(a)
{
    int len;
    len = strlen(a.mainprod);
    mainprod = new char[len + 1];
    strcpy(mainprod, a.mainprod);
}

Classic & Classic::operator=(const Classic & a)
{
    //先要用基类的重载= 给基类部分赋值
    Cd::operator=(a);
    delete[]mainprod;
    int len;
    len = strlen(a.mainprod);
    mainprod = new char[len + 1];
    strcpy(mainprod, a.mainprod);
    //别忘记要返回值
    return *this;
}

void Classic::Report() const
{
    Cd::Report();
    cout << " mainproduction: " << mainprod << endl;
}
method.cpp
#include<iostream>
using namespace std;
#include"classic.h"    //will contain #include cd.h
void Bravo(const Cd & disk);
//记住要自己修改cd.h文件
int main()
{
    Cd c1("Beatles", "Capitol", 14, 35.5);
    Classic  c2 = Classic("Piano Sonata in B flat, Fantasia in C", "Alfred Brendel", "Philios", 2, 57.17);

    Cd * pcd = &c1;

    cout << "using object directly:\n";
    c1.Report();
    c2.Report();
    
    //Cd sd;

    cout << "using type cd * pointer to object:\n";
    pcd->Report();
    pcd = &c2;
    pcd->Report();

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

    cout << "testing assignment" << endl;
    Classic copy;
    copy = c2;
    copy.Report();
    return 0;
}

void Bravo(const Cd & disk)
{
    disk.Report();
}
test.cpp

  先调用基类构造,再调用派生类构造,析构函数则相反,先调用派生类析构,再调用基类的析构函数。

  派生类的析构只用删除派生里的新成员,而不用管基类部分,因为派生类析构函数会自动调用基类的析构函数,所以他自身的职责是对派生类的构造函数执行工作的清理

猜你喜欢

转载自www.cnblogs.com/syne-cllf/p/9266589.html