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;
}