C++编程思想 第1卷 第15章 多态性和虚函数 析构函数和虚拟析构函数 创建基于对象的继承

在对容器类Stack和Stash的描述中,有一点是重复出现的,这就是 所有权问题。

在第14章的例子InheritStack.cpp中提出了一种解决办法,从Stack继承出
一个仅可以接收和生成string指针的类

问题是我们希望容器可以容纳更多的类型,但我们不想使用void指针

这种方法使用单根继承或基于对象的继承。可以看到使用单根继承还有其他
一些优点

为了解决所有权问题,可以创建一个相当简单的类Object作为基类,它仅
包含一个虚析构函数

//: C15:OStack.h
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
// Using a singly-rooted hierarchy
#ifndef OSTACK_H
#define OSTACK_H

class Object {
public:
  virtual ~Object() = 0;
};

// Required definition:
inline Object::~Object() {}

class Stack {
  struct Link {
    Object* data;
    Link* next;
    Link(Object* dat, Link* nxt) : 
      data(dat), next(nxt) {}
  }* head;
public:
  Stack() : head(0) {}
  ~Stack(){ 
    while(head)
      delete pop();
  }
  void push(Object* dat) {
    head = new Link(dat, head);
  }
  Object* peek() const { 
    return head ? head->data : 0;
  }
  Object* pop() {
    if(head == 0) return 0;
    Object* result = head->data;
    Link* oldHead = head;
    head = head->next;
    delete oldHead;
    return result;
  }
};
#endif // OSTACK_H ///:~

通过把所有的东西放在头文件中来简化问题,纯虚析构函数的定义以内联
形式置于头文件中,并且pop()也是内联的

Link对象现在是指向Object指针,而不是void指针,并且Stack也将仅仅接收
和返回Object指针

//: C15:OStackTest.cpp
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
//{T} OStackTest.cpp
#include "OStack.h"
#include "../require.h"
#include <fstream>
#include <iostream>
#include <string>
using namespace std;

// Use multiple inheritance. We want 
// both a string and an Object:
class MyString: public string, public Object {
public:
  ~MyString() {
    cout << "deleting string: " << *this << endl;
  }
  MyString(string s) : string(s) {}
};

int main(int argc, char* argv[]) {
  requireArgs(argc, 1); // File name is argument
  ifstream in(argv[1]);
  assure(in, argv[1]);
  Stack textlines;
  string line;
  // Read file and store lines in the stack:
  while(getline(in, line))
    textlines.push(new MyString(line));
  // Pop some lines from the stack:
  MyString* s;
  for(int i = 0; i < 10; i++) {
    if((s=(MyString*)textlines.pop())==0) break;
    cout << *s << endl;
    delete s; 
  }
  cout << "Letting the destructor do the rest:"
    << endl;
  getchar();
} ///:~

从10个元素从栈中弹出,这意味着还保留了一些对象

创建包容Object的容器是一种合理的方法--如果使用单根继承

输出
} ///:~
deleting string: } ///:~
  getchar();
deleting string:   getchar();
    << endl;
deleting string:     << endl;
  cout << "Letting the destructor do the rest:"
deleting string:   cout << "Letting the destructor do the rest:"
  }
deleting string:   }
    delete s;
deleting string:     delete s;
    cout << *s << endl;
deleting string:     cout << *s << endl;
    if((s=(MyString*)textlines.pop())==0) break;
deleting string:     if((s=(MyString*)textlines.pop())==0) break;
  for(int i = 0; i < 10; i++) {
deleting string:   for(int i = 0; i < 10; i++) {
  MyString* s;
deleting string:   MyString* s;
Letting the destructor do the rest:

猜你喜欢

转载自blog.csdn.net/eyetired/article/details/81357186