编程练习
1.以下面的类声明为基础:
Cd.h
//
// Created by Reza on 2021/3/18.
//
#ifndef CD_CD_H
#define CD_CD_H
class Cd {
private:
char performance[50];
char label[20];
int selections;
double playtime;
public:
Cd(char *s1,char *s2,int n,double x);
Cd(const Cd &d);
Cd();
virtual ~Cd(){};
virtual void Report() const;
// Cd & operator=(const Cd &d);
};
class Classic : public Cd
{
private:
char work[20];
public:
Classic(char *s1,char *s2,char *s3,int n,double x);
// Classic(const Classic &c);
Classic();
virtual ~Classic(){};
virtual void Report() const;
Classic & operator=(const Classic &c);
};
#endif //CD_CD_H
Cd.cpp
//
// Created by Reza on 2021/3/18.
//
#include "Cd.h"
#include
#include
Cd::Cd(char *s1, char *s2, int n, double x) {
// performance = new char[strlen(s1)+1];
std::strcpy(performance, s1);
std::strcpy(label, s2);
selections = n;
playtime = x;
}
Cd::Cd() {
std::strcpy(performance,"None");
std::strcpy(label,"None");
selections = 0;
playtime = 0;
}
Cd::Cd(const Cd &d) {
std::strcpy(performance,d.performance);
std::strcpy(label,d.label);
selections=d.selections;
playtime=d.playtime;
}
void Cd::Report() const {
std::cout << "performance: " << performance << '\n';
std::cout << "label: " << label <<'\n';
std::cout << "selection: " << selections << '\n';
std::cout << "playtime: " << playtime << "\n";
}
//Cd & Cd::operator=(const Cd &d) {
// if (this == &d)
// return *this;
// std::strcpy(performance,d.performance);
// std::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(s1,s2,n,x)
{
std::strcpy(work,s3);
}
Classic::Classic() {
std::strcpy(work,"None");
}
//Classic::Classic(const Classic &c){
// std::strcpy(work,c.work);
//}
void Classic::Report() const {
Cd::Report();
std::cout << "work: " << work <<'\n';
}
Classic & Classic::operator=(const Classic &c) {
if (this == &c)
return *this;
std::strcpy(work,c.work);
return *this;
}
main.cpp
#include
using namespace std;
#include "Cd.h"
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 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: ";
Classic copy;
copy = c2;
copy.Report();
return 0;
}
void Bravo(const Cd & disk)
{
disk.Report();
}
2.完成练习1,但让两个类使用动态内存分配为不是长度固定的数组来记录字符串。
Cd.h
//
// Created by Reza on 2021/3/18.
//
#ifndef CD_CD_H
#define CD_CD_H
class Cd {
private:
char *performance;
char *label;
int selections;
double playtime;
public:
Cd(char *s1,char *s2,int n,double x);
Cd(const Cd &d);
Cd();
virtual ~Cd();
virtual void Report() const;
// Cd & operator=(const Cd &d);
};
class Classic : public Cd
{
private:
char *work;
public:
Classic(char *s1,char *s2,char *s3,int n,double x);
// Classic(const Classic &c);
Classic();
virtual ~Classic();
virtual void Report() const;
Classic & operator=(const Classic &c);
};
#endif //CD_CD_H
Cd.cpp
//
// Created by Reza on 2021/3/18.
//
#include "Cd.h"
#include
#include
Cd::Cd(char *s1, char *s2, int n, double x) {
performance = new char[std::strlen(s1)+1];
label = new char[std::strlen(s2)+1];
std::strcpy(performance, s1);
std::strcpy(label, s2);
selections = n;
playtime = x;
}
Cd::Cd() {
performance = new char[5];
label = new char[5];
std::strcpy(performance,"None");
std::strcpy(label,"None");
selections = 0;
playtime = 0;
}
Cd::Cd(const Cd &d) {
performance = new char[std::strlen(d.performance)+1];
label = new char[std::strlen(d.label)+1];
std::strcpy(performance,d.performance);
std::strcpy(label,d.label);
selections=d.selections;
playtime=d.playtime;
}
Cd::~Cd() {
delete [] performance;
delete [] label;
}
void Cd::Report() const {
std::cout << "performance: " << performance << '\n';
std::cout << "label: " << label <<'\n';
std::cout << "selection: " << selections << '\n';
std::cout << "playtime: " << playtime << "\n";
}
//Cd & Cd::operator=(const Cd &d) {
// if (this == &d)
// return *this;
// std::strcpy(performance,d.performance);
// std::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(s1,s2,n,x)
{
work = new char [strlen(s3)+1];
std::strcpy(work,s3);
}
Classic::Classic() {
work = new char [5];
std::strcpy(work,"None");
}
Classic::~Classic() {
delete [] work;
}
//Classic::Classic(const Classic &c){
// std::strcpy(work,c.work);
//}
void Classic::Report() const {
Cd::Report();
std::cout << "work: " << work <<'\n';
}
Classic & Classic::operator=(const Classic &c) {
if (this == &c)
return *this;
Cd::operator=(c);
delete [] work;
work = new char (std::strlen(c.work)+1);
std::strcpy(work,c.work);
return *this;
}
main.cpp
#include
using namespace std;
#include "Cd.h"
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 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: ";
Classic copy;
copy = c2;
copy.Report();
return 0;
}
void Bravo(const Cd & disk)
{
disk.Report();
}
3.修改baseDMA-lacksDMA-hasDMA类层次,让三个类都从一个ABC派生而来,然后使用与程序清单13.10相似的程序对结果进行测试。也就是说,它应使用ABC指针数组,并让用户决定要创建的对象类型。在类定义中添加virtual View()方法以处理数据显示。
DMA.h
// dma.h -- inheritance and dynamic memory allocation
#ifndef DMA_H_
#define DMA_H_
#include
// Base Class Using DMA
class ABC_DMA
{
private:
char *label;
int rating;
public:
ABC_DMA(const char *s1= nullptr,int r1=0);
ABC_DMA(const ABC_DMA &a);
virtual ~ABC_DMA(){delete [] label;};
virtual void View() const;
ABC_DMA & operator=(const ABC_DMA &a);
friend std::ostream & operator<<(std::ostream & os,const ABC_DMA &a);
};
class baseDMA: public ABC_DMA
{
private:
public:
baseDMA(const char *l = "null", int r = 0);
friend std::ostream & operator<<(std::ostream & os,
const baseDMA & rs);
};
class lacksDMA :public ABC_DMA
{
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_DMA & rs);
virtual void View() const;
friend std::ostream & operator<<(std::ostream & os,
const lacksDMA & rs);
};
// derived class with DMA
class hasDMA :public ABC_DMA
{
private:
char * style;
public:
hasDMA(const char * s = "none", const char * l = "null",
int r = 0);
hasDMA(const char * s, const ABC_DMA & rs);
hasDMA(const hasDMA & hs);
~hasDMA();
virtual void View() const;
hasDMA & operator=(const hasDMA & rs);
friend std::ostream & operator<<(std::ostream & os,
const hasDMA & rs);
};
#endif
DMA.cpp
//
// Created by Reza on 2021/3/18.
//
#include "DMA.h"
#include
#include
ABC_DMA::ABC_DMA(const char *s1, int r1) {
label = new char [strlen(s1)+1];
strcpy(label,s1);
rating=r1;
}
ABC_DMA::ABC_DMA(const ABC_DMA &a) {
label = new char [strlen(a.label)+1];
strcpy(label,a.label);
rating=a.rating;
}
void ABC_DMA::View() const {
std::cout << "label: " << label <<'\n';
std::cout << "rating: " << rating << '\n';
}
ABC_DMA & ABC_DMA::operator=(const ABC_DMA &a)
{
label = new char [strlen(a.label)+1];
strcpy(label,a.label);
rating=a.rating;
return *this;
}
std::ostream & operator<<(std::ostream & os,const ABC_DMA &a)
{
os << "label: " << a.label << "rating: " << a.rating << '\n';
return os;
}
// baseDMA methods
baseDMA::baseDMA(const char * l, int r):ABC_DMA(l,r)
{}
std::ostream & operator<<(std::ostream & os, const baseDMA & rs)
{
os << (const ABC_DMA &)rs;
return os;
}
// lacksDMA methods
lacksDMA::lacksDMA(const char * c, const char * l, int r)
: ABC_DMA(c,r)
{
strcpy(color,l);
}
lacksDMA::lacksDMA(const char * c, const ABC_DMA & rs)
: ABC_DMA(rs)
{
strcpy(color,c);
}
void lacksDMA::View() const {
ABC_DMA::View();
std::cout << "color: " << color << '\n';
}
std::ostream & operator<<(std::ostream & os, const lacksDMA & ls)
{
os << (const baseDMA &) ls;
os << "Color: " << ls.color << std::endl;
return os;
}
// hasDMA methods
hasDMA::hasDMA(const char * s, const char * l, int r)
: ABC_DMA(l, r)
{
style = new char[std::strlen(s) + 1];
std::strcpy(style, s);
}
hasDMA::hasDMA(const char * s, const ABC_DMA & rs)
: ABC_DMA(rs)
{
style = new char[std::strlen(s) + 1];
std::strcpy(style, s);
}
hasDMA::hasDMA(const hasDMA & hs)
: ABC_DMA(hs) // invoke base class copy constructor
{
style = new char[std::strlen(hs.style) + 1];
std::strcpy(style, hs.style);
}
hasDMA::~hasDMA()
{
delete [] style;
}
void hasDMA::View() const {
ABC_DMA::View();
std::cout << style << '\n';
}
hasDMA & hasDMA::operator=(const hasDMA & hs)
{
if (this == &hs)
return *this;
ABC_DMA::operator=(hs); // copy base portion
delete [] style; // prepare for new style
style = new char[std::strlen(hs.style) + 1];
std::strcpy(style, hs.style);
return *this;
}
std::ostream & operator<<(std::ostream & os, const hasDMA & hs)
{
os << (const baseDMA &) hs;
os << "Style: " << hs.style << std::endl;
return os;
}
main.cpp
#include
using namespace std;
#include "DMA.h"
int main() {
using std::cout;
using std::endl;
using std::string;
char s1[20];
int rating;
unsigned int number;
ABC_DMA *p[4];
for (int i = 0; i < 4; ++i) {
cout << "Enter label name: ";
cin >> s1;
cout << "Enter rating: ";
cin >> rating;
cout << "Enter 1 : baseDMA \n 2 : lackDMA \n 3 : hasDMA \n to choose DMA: ";
while (cin >> number&&(number!=1&&number!=2&&number!=3))
cout << "Please Enter 1/2/3 !";
if (number == 1)
p[i] = new baseDMA(s1,rating);
else if (number==2)
{
char color[40];
cout << "Please enter color:";
cin >> color;
p[i] = new lacksDMA(color,s1,rating);
}
else if (number==3)
{
char style[40];
cout << "Please enter style:";
cin >> style;
p[i] = new hasDMA(style,s1,rating);
}
}
for(int i=0;i<4;i++)
{
p[i]->View();
}
}
4.Benevolent Order of Programmers 用来维护瓶装葡萄酒。为描述它,BOP Portmaster 设置了一个 Port类,其声明如下:
#include
using namespace std;
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);
};
Vintage类如下所示:
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);
};
a.第一个任务是重新创建Port方法定义,因为前任被开除时销毁了方法定义。
#include "Port.h"
#include
#include
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) {
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;
}
Port & Port::operator+=(int b) {
bottles = bottles + b;
}
Port & Port::operator-=(int b) {
bottles = bottles - b;
}
void Port::Show() const {
cout << "Brand: " << brand << endl;
cout << "Kind: " << style << endl;
cout << "Bottles: " << bottles << endl;
}
ostream & operator<<(ostream & os,const Port & p)
{
os << p.brand <<", " << p.style << ", " << p.bottles;
return os;
}
b.第二个任务是解释为什么有的方法重新定义了,而有些没有重新定义。
由于有些方法在派生类中需要添加更多的功能,而有些方法只需要承担基类中的功能。
c.第三个任务是解释为何没有将operator=()和operator()声明为虚的。
因为基类Port与派生类VintagePort中的operator=()和operator()中所包含的参数不一样,而虚函数要求派生类和基类的方法名和参数列表相同。
d.第四个任务是提供VintagePort中各个方法的定义。
VintagePort::VintagePort(const char *br, int b, const char *nn, int y) :Port(br,"none",b){
nickname = new char [strlen(nn)+1];
strcpy(nickname,nn);
year = y;
}
VintagePort::VintagePort() {
nickname = nullptr;
year = 0;
}
VintagePort::VintagePort(const VintagePort &vp) :Port(vp){
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;
Port::operator=(vp);
delete [] nickname;
nickname = new char [strlen(vp.nickname)+1];
strcpy(nickname,vp.nickname);
year = vp.year;
}
void VintagePort::Show() const {
Port::Show();
cout << "nickname: " << nickname << endl;
cout << "year: " << year << endl;
}
ostream & operator<<(ostream &os,const VintagePort & vp){
os << (const Port &)vp <