C++ Primer Plus习题及答案-第十三章

习题选自:C++ Primer Plus(第六版)
内容仅供参考,如有错误,欢迎指正 !

第十三章- 类继承学习笔记

复习题

1. 派生类从基类那里继承了什么?

派生类继承了基类的公有成员、基类的保护成员和基类的私有成员,但派生类不能直接访问从基类继承过来的私有成员。

2. 派生类不能从基类那里继承什么?

派生类不能继承构造函、析构函数、赋值运算符合友元。

3. 假设baseDMA::operator=()函数的返回类型为void,而不是baseDMA &,这将有什么后果?如果返回类型为baseDMA,而不是baseDMA &,又将有什么后果?

如果返回值为void的,则baseDMA对象仍可以使用单个赋值,但是不能使用连续赋值。即:

baseDMA magazine("Pandering to Glitz", 1);
baseDMA gift1, gift2, gift3;
gift1 = magazine;          //ok
gitft2 = gift3 = gift1;    //no 不可用

如果方法返回类型为baseDMA,则该方法返回的是一个对象,不是引用,导致返回语句的时候需要复制对象,导致该方法执行速度会有所减慢。

4. 创建和删除派生类对象时,构造函数和析构函数调用的顺序是怎样的?

按照派生的顺序调用构造函数,最早的构造函数最先调用。调用析构函数的顺序正好相反。

5. 如果派生类没有添加任何数据成员,它是否需要构造函数?

需要,每个类都必须有自己的构造函数,如果派生类没有添加新成员,则构造函数可以为空,但必须存在。

6. 如果基类和派生类定义了同名的方法,当派生类对象调用该方法时,被调用的将是哪个方法?

调用派生类方法,它取代基类定义。仅当派生类没有重新定义方法或使用作用域解析运算符时,才会调用基类方法。

7. 在什么情况下,派生类应定义赋值运算符?

如果派生类构造函数使用new或者new[]运算符来初始化类的指针成员,则应定义一个赋值运算符。更普通的说,如果对于派生类成员来说,默认赋值不正确,则应定义赋值运算符。

8. 可以将派生类对象的地址赋给基类指针吗?可以将基类对象的地址赋给派生类指针吗?

可以将派生类对象的地址赋给基类指针。但只有通过显示类型转换,才可以将基类对象的地址赋给派生类指针(向下转换),而使用这样的指针不一定安全。

9. 可以将派生类对象赋给基类对象吗?可以将基类对象赋给派生类对象吗?

可以将派生类对象的地址赋值给基类对象,对于派生类中新增的数据成员都不会传递给基类对象,程序也将使用基类的赋值运算符。仅当派生类定义了转换运算符(即包含将基类引用作为唯一参数的构造函数)或使用基类为参数的赋值运算符时,相反的赋值才是可能的。

10. 假设定义了一个函数,它将基类对象的引用作为参数。为什么该函数也可以将派生类对象作为参数?

应为c++允许基类引用指向从该基类派生而来的任何类型。

11. 假设定义了一个函数,它将基类对象作为参数(即函数按值传递基类对象)。为什么该函数也可以将派生类对象作为参数?

按值传递对象将调用复制构造函数,由于形参是基类对象,因此将调用基类的复制构造函数,复制构造函数已基类引用为参数,该引用可以将指向作为参数传递的派生对象,最终的结构是,将生成一个新的基类对象,其成员对应于派生类对象的基类部分。

12. 为什么通常按引用传递对象比按值传递对象的效率更高?

按引用传递对象,这样可以确保函数从虚函数受益。另外,按引用传递对象可以节省内存和时间,尤其对于大型对象。按值传递对象的主要有点在于可以保护原始数据,但可以通过将引用作为const类型传递,来达到同样的目的。

13. 假设Corporation是基类,PublicCorporation是派生类。再假设这两个类都定义了head()函数,ph是指向Corporation类型的指针,且被赋给了一个PublicCorporation对象的地址。如果基类将head( )定义为:
a. 常规非虚方法;
b. 虚方法;
ph->head()将被如何解释?

a. ph-head()调用Corporation::head();

b. ph-head()调用PublicCorporation::head();

14. 下述代码有什么问题?
class Kitchen
{
    private:
    double kit_sq_ft;
    public:
    Kitchen() { kit_sq_ft = 0.0; }
    virtual double area() const { return kit_sq_ft * kit_sq_ft; }
};
class House : public Kitchen
{
    private:
    double all_sq_ft;
    public: 
    House() { all_sq_ft += kit_sq_ft;}
    double area(const char *s) const { cout << s; return all_sq_ft; }
};

首先,这种情况不符合is-a模型,因此公有继承不适用。其次,House中area()定义成带参数的,将隐藏area()Kitchen版本。

编程练习

1. 以下面的类声明为基础:
// base class
class Cd { // represents a CD disk
    private:
    char performers[50];
    char label[20];
    int selections; // number of selections
    double playtime; // playing time in minutes
    public:
    Cd(char * s1, char * s2, int n, double x);
    Cd(const Cd & d);
    Cd();
    ~Cd();
    void Report() const; // reports all CD data
    Cd & operator=(const Cd & d);
};
派生出一个Classic类,并添加一组char成员,用于存储指出CD中主要作品的字符串。修改上述声明,使基类的所有函数都是虚的。如果上述定义声明的某个方法并不需要,则请删除它。使用下面的程序测试您的产品:
#include <iostream>
using namespace std;
#include "classic.h" // which will contain #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(); // use Cd method
    c2.Report(); // use Classic method
    cout << "Using type cd * pointer to objects:\n";
    pcd->Report(); // use Cd method for cd object
    pcd = &c2;
    pcd->Report(); // use Classic method for classic object
    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();
}

classic.h:

// base class
class Cd {  // represents a CD disk
 private:
  char performers[50];
  char label[20];
  int selections;   // number of selections
  double playtime;  // playing time in minutes
 public:
  Cd(char* s1, char* s2, int n, double x);
  Cd(const Cd& d);
  Cd();
  virtual ~Cd();
  virtual void Report() const;  // reports all CD data
  virtual Cd& operator=(const Cd& d);
};

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

 public:
  Classic(char* sc, char* s1, char* s2, int n, double x);
  Classic(const Classic& c);
  Classic();
  virtual ~Classic();
  virtual void Report() const;
  virtual Classic& operator=(const Classic& c);
};

classic.cpp:

#include "classic.h"

#include <cstring>
#include <iostream>

Cd::Cd(char* s1, char* s2, int n, double x) {
  std::strncpy(performers, s1, 50);
  std::strncpy(label, s2, 20);
  selections = n;
  playtime = x;
}

Cd::Cd(const Cd& d) {
  std::strncpy(performers, d.performers, 50);
  std::strncpy(label, d.label, 20);
  selections = d.selections;
  playtime = d.playtime;
}
Cd::Cd() {
  performers[0] = '\0';
  label[0] = '\0';
  selections = 0;
  playtime = 0;
}
Cd::~Cd() {}

void Cd::Report() const {
  std::cout << "Performers: " << performers << std::endl;
  std::cout << "Label: " << label << std::endl;
  std::cout << "Selections: " << selections << std::endl;
  std::cout << "PlayTime: " << playtime << std::endl;
}

Cd& Cd::operator=(const Cd& d) {
  if (&d == this) return *this;
  std::strncpy(performers, d.performers, 50);
  std::strncpy(label, d.label, 20);
  selections = d.selections;
  playtime = d.playtime;
  return *this;
}

Classic::Classic(char* sc, char* s1, char* s2, int n, double x)
    : Cd(s1, s2, n, x) {
  primary_work = new char[std::strlen(sc) + 1];
  std::strcpy(primary_work, sc);
}

Classic::Classic(const Classic& c) : Cd(c) {
  primary_work = new char[std::strlen(c.primary_work) + 1];
  std::strcpy(primary_work, c.primary_work);
}

Classic::Classic() : Cd() { primary_work = nullptr; }

Classic::~Classic() { delete[] primary_work; }

void Classic::Report() const {
  Cd::Report();
  std::cout << "PrimaryWork: " << primary_work << std::endl;
}

Classic& Classic::operator=(const Classic& c) {
  if (&c == this) return *this;
  delete[] primary_work;
  Cd::operator=(c);
  primary_work = new char[std::strlen(c.primary_work) + 1];
  std::strcpy(primary_work, c.primary_work);
  return *this;
}

main.cpp:

#include <iostream>
using namespace std;
#include "classic.h"  // which will contain #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();  // use Cd method
  c2.Report();  // use Classic method
  cout << "Using type cd * pointer to objects:\n";
  pcd->Report();  // use Cd method for cd object
  pcd = &c2;
  pcd->Report();  // use Classic method for classic object
  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,但让两个类使用动态内存分配而不是长度固定的数组来记录字符串。

classic.h:

// base class
class Cd {  // represents a CD disk
 private:
  char* performers;
  char* label;
  int selections;   // number of selections
  double playtime;  // playing time in minutes
 public:
  Cd(char* s1, char* s2, int n, double x);
  Cd(const Cd& d);
  Cd();
  virtual ~Cd();
  virtual void Report() const;  // reports all CD data
  virtual Cd& operator=(const Cd& d);
};

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

 public:
  Classic(char* sc, char* s1, char* s2, int n, double x);
  Classic(const Classic& c);
  Classic();
  virtual ~Classic();
  virtual void Report() const;
  virtual Classic& operator=(const Classic& c);
};

classic.cpp:

#include "classic.h"

#include <cstring>
#include <iostream>

Cd::Cd(char* s1, char* s2, int n, double x) {
  performers = new char[std::strlen(s1) + 1];
  label = new char[std::strlen(s2) + 1];
  std::strcpy(performers, s1);
  std::strcpy(label, s2);
  selections = n;
  playtime = x;
}

Cd::Cd(const Cd& d) {
  performers = new char[std::strlen(d.performers) + 1];
  label = new char[std::strlen(d.label) + 1];
  std::strcpy(performers, d.performers);
  std::strcpy(label, d.label);
  selections = d.selections;
  playtime = d.playtime;
}
Cd::Cd() {
  performers = nullptr;
  label = nullptr;
  selections = 0;
  playtime = 0;
}
Cd::~Cd() {
  delete[] performers;
  delete[] label;
}

void Cd::Report() const {
  std::cout << "Performers: " << performers << std::endl;
  std::cout << "Label: " << label << std::endl;
  std::cout << "Selections: " << selections << std::endl;
  std::cout << "PlayTime: " << playtime << std::endl;
}

Cd& Cd::operator=(const Cd& d) {
  if (&d == this) return *this;
  std::strncpy(performers, d.performers, 50);
  std::strncpy(label, d.label, 20);
  selections = d.selections;
  playtime = d.playtime;
  return *this;
}

Classic::Classic(char* sc, char* s1, char* s2, int n, double x)
    : Cd(s1, s2, n, x) {
  primary_work = new char[std::strlen(sc) + 1];
  std::strcpy(primary_work, sc);
}

Classic::Classic(const Classic& c) : Cd(c) {
  primary_work = new char[std::strlen(c.primary_work) + 1];
  std::strcpy(primary_work, c.primary_work);
}

Classic::Classic() : Cd() { primary_work = nullptr; }

Classic::~Classic() { delete[] primary_work; }

void Classic::Report() const {
  Cd::Report();
  std::cout << "PrimaryWork: " << primary_work << std::endl;
}

Classic& Classic::operator=(const Classic& c) {
  if (&c == this) return *this;
  delete[] primary_work;
  Cd::operator=(c);
  primary_work = new char[std::strlen(c.primary_work) + 1];
  std::strcpy(primary_work, c.primary_work);
  return *this;
}

main.cpp:

#include <iostream>
using namespace std;
#include "classic.h"  // which will contain #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();  // use Cd method
  c2.Report();  // use Classic method
  cout << "Using type cd * pointer to objects:\n";
  pcd->Report();  // use Cd method for cd object
  pcd = &c2;
  pcd->Report();  // use Classic method for classic object
  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()方法以处理数据显示。

abc.h:

#ifndef ABC_H_
#define ABC_H_

#include <iostream>
class ABC {
 private:
  char* label;
  int rating;

 public:
  ABC(const char* l = "null", int r = 1);
  ABC(const ABC& a);
  virtual ~ABC() = 0;
  virtual void View() const;
  ABC& operator=(const ABC& a);
  friend std::ostream& operator<<(std::ostream& os, const ABC& a);
};

class baseDMA : public ABC {
 private:
 public:
  baseDMA(const char* l = "null", int r = 0);
  friend std::ostream& operator<<(std::ostream& os, const baseDMA& rs);
};

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& a);
  virtual void View() const;
  friend std::ostream& operator<<(std::ostream& os, const lacksDMA& rs);
};

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& c);
  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  // ABC_H_

abc.cpp:

#include "abc.h"

#include <cstring>

ABC::ABC(const char* l, int r) {
  label = new char(std::strlen(l) + 1);
  std::strcpy(label, l);
  rating = r;
}
ABC::ABC(const ABC& a) {
  label = new char(std::strlen(a.label) + 1);
  std::strcpy(label, a.label);
  rating = a.rating;
}

ABC::~ABC() { delete[] label; }

void ABC::View() const { std::cout << *this << std::endl; }

ABC& ABC::operator=(const ABC& a) {
  if (&a == this) return *this;
  delete[] label;
  label = new char[std::strlen(a.label) + 1];
  std::strcpy(label, a.label);
  rating = a.rating;
}

std::ostream& operator<<(std::ostream& os, const ABC& a) {
  os << "label: " << a.label << ", rating: " << a.rating;
  return os;
}

/***************baseDMA************/

baseDMA::baseDMA(const char* l, int r) : ABC(l, r) {}

std::ostream& operator<<(std::ostream& os, const baseDMA& rs) {
  os << (const ABC&)rs;
  return os;
}

/***************lacksDMA************/
lacksDMA::lacksDMA(const char* c, const char* l, int r) : ABC(l, r) {
  std::strncpy(color, c, COL_LEN);
}

lacksDMA::lacksDMA(const char* c, const ABC& a) : ABC(a) {
  std::strncpy(color, c, COL_LEN);
}

void lacksDMA::View() const { std::cout << *this << std::endl; }

std::ostream& operator<<(std::ostream& os, const lacksDMA& rs) {
  os << (const ABC&)rs << ", color: " << rs.color;
  return os;
}

/***************hasDMA************/
hasDMA::hasDMA(const char* s, const char* l, int r) : ABC(l, r) {
  style = new char[std::strlen(s) + 1];
  std::strcpy(style, s);
}

hasDMA::hasDMA(const char* s, const ABC& c) : ABC(c) {
  style = new char[std::strlen(s) + 1];
  std::strcpy(style, s);
}

hasDMA::hasDMA(const hasDMA& hs) : ABC(hs) {
  style = new char[std::strlen(hs.style) + 1];
  std::strcpy(style, hs.style);
}

hasDMA::~hasDMA() { delete[] style; }

void hasDMA::View() const { std::cout << *this << std::endl; }

hasDMA& hasDMA::operator=(const hasDMA& hs) {
  if (this == &hs) return *this;
  ABC::operator=(hs);
  delete[] style;
  style = new char[std::strlen(hs.style) + 1];
  std::strcpy(style, hs.style);

  return *this;
}

std::ostream& operator<<(std::ostream& os, const hasDMA& rs) {
  os << (const ABC&)rs << ", style: " << rs.style;
  return os;
}

main.cpp:

#include <iostream>

#include "abc.h"

int main() {
  using std::cout;
  using std::endl;

  baseDMA shirt("Portrabelly", 8);
  lacksDMA balloon("red", "Blumpo", 4);
  hasDMA map("Mercator", "Buffalo Kyes", 5);
  cout << shirt << endl;
  cout << balloon << endl;
  cout << map << endl;
  lacksDMA balloon2(balloon);
  hasDMA map2;
  map2 = map;
  cout << balloon2 << endl;
  cout << map2 << endl;

  ABC* pts[3];
  pts[0] = &shirt;
  pts[1] = &balloon;
  pts[2] = &map;

  for (int i = 0; i < 3; ++i) cout << *pts[i] << endl;
  for (int i = 0; i < 3; ++i) pts[i]->View();

  return 0;
}
4. Benevolent Order of Programmers用来维护瓶装葡萄酒箱。为描述它,BOP Portmaster设置了一个Port类,其声明如下
#include <iostream>
using namespace std;
class Port
{
    private:
    char * brand;
    char style[20]; // i.e., tawny, ruby, vintage
    int bottles;
    public:
    Port(const char * br = "none", const char * st = "none", int b = 0);
    Port(const Port & p); // copy constructor
    virtual ~Port() { delete [] brand; }
    Port & operator=(const Port & p);
    Port & operator+=(int b); // adds b to bottles
    Port & operator-=(int b); // subtracts b from bottles, if available
    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完成了Por类的方法定义后派生了VintagePort类,然后被解职——因为不小心将一瓶45度Cockburn泼到了正在准备烤肉调料的人身上,VintagePort类如下所示:
class VintagePort : public Port // style necessarily = "vintage"
{
    private:
    char * nickname; // i.e., "The Noble" or "Old Velvet", etc.
    int year; // vintage 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<<()声明为虚的。
d. 第四个任务是提供VintagePort中各个方法的定义。

port.h:

#ifndef PORT_H_
#define PORT_H_

#include <iostream>
using namespace std;
class Port {
 private:
  char* brand;
  char style[20];  // i.e., tawny, ruby, vintage
  int bottles;

 public:
  Port(const char* br = "none", const char* st = "none", int b = 0);
  Port(const Port& p);  // copy constructor
  virtual ~Port() { delete[] brand; }
  Port& operator=(const Port& p);
  //派生类的计算逻辑与基类一致,且在该方法中派生类未操作其新增成员,因此该函数在派生类中不需要重新定义
  Port& operator+=(int b);  // adds b to bottles
  //派生类的计算逻辑与基类一致,且在该方法中派生类未操作其新增成员,因此该函数在派生类中不需要重新定义
  Port& operator-=(int b);  // subtracts b from bottles, if available
  int BottleCount() const { return bottles; }
  virtual void Show() const;
  friend ostream& operator<<(ostream& os, const Port& p);
};

class VintagePort : public Port  // style necessarily = "vintage"
{
 private:
  char* nickname;  // i.e., "The Noble" or "Old Velvet", etc.
  int year;        // vintage 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);//增加了新的成员nickname和year,且赋值运算符不能被继承,需要重新定义
  void Show() const;//增加了新的成员nickname和year,需要重新定义
  friend ostream& operator<<(ostream& os, const VintagePort& vp);//友元函数不属于成员函数,无法继承
};

#endif  // PORT_H_

port.cpp:

#include "port.h"

#include <cstring>

Port::Port(const char* br, const char* st, int b) {
  brand = new char[strlen(br) + 1];
  strcpy(brand, br);
  strncpy(style, st, 20);
  bottles = b;
}

Port::Port(const Port& p) {
  brand = new char[strlen(p.brand) + 1];
  strcpy(brand, p.brand);
  strncpy(style, p.style, 20);
  bottles = p.bottles;
}

Port& Port::operator=(const Port& p) {
  if (&p == this) return *this;
  delete[] brand;
  brand = new char[strlen(p.brand) + 1];
  strcpy(brand, p.brand);
  strncpy(style, p.style, 20);
  bottles = p.bottles;
  return *this;
}

Port& Port::operator+=(int b) {
  bottles += b;
  return *this;
}

Port& Port::operator-=(int b) {
  bottles -= b;
  return *this;
}

void Port::Show() const {
  cout << "Brand: " << brand << endl;
  cout << "Style: " << style << endl;
  cout << "Bottles: " << bottles << endl;
}

ostream& operator<<(ostream& os, const Port& p) {
  os << p.brand << ", " << p.style << ", " << p.bottles;
  return os;
}

VintagePort::VintagePort() : Port() {
  nickname = new char[strlen("none") + 1];
  strcpy(nickname, "none");
  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) {
  nickname = new char[std::strlen(vp.nickname) + 1];
  std::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[std::strlen(vp.nickname) + 1];
  std::strcpy(nickname, vp.nickname);
  year = vp.year;

  return *this;
}

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;
  os << ", " << vp.nickname << ", " << vp.year;
  return os;
}

main.cpp:

#include <iostream>

#include "port.h"

int main() {
  Port p1;
  Port p2("Abc", "Bcc", 30);
  std::cout << p1 << std::endl;
  std::cout << p2 << std::endl;
  Port p3 = p2;
  p3.Show();
  p3 += 3;
  p3.Show();
  Port p4 = p2;
  p3 -= 2;
  p3.Show();

  VintagePort vp1("Vabc", 50, "hn", 1983);
  vp1.Show();
  VintagePort vp2;
  vp2.Show();
  vp1 -= 3;
  vp2 = vp1;
  std::cout << vp2 << std::endl;

  return 0;
}
  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艰默

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值