现在的位置: 首页 > 综合 > 正文

一个类继承的问题

2013年10月07日 ⁄ 综合 ⁄ 共 2332字 ⁄ 字号 评论关闭

FAQ   8.14

        如果"苹果袋"以kind-of方式继承至"水果袋",那么"水果袋"中就允许放入任何种类以kind-of方式从水果继承来的具体水果么?

        原文描述 :Is bag-of-apple a kind-of bag-of-fruit, assuming bag-of-fruit allows the insertion of any kind-of fruit?

 

        下表中, Fruit是一个基类, Apple和Banana是Kinds-of方式继承至Fruit类的具体的类.下面是UML框图和代码:

graphics/08fig02.gif

 

 

        下面的BagOfFruit类允许插入和移除任何kind-of Fruit.

#include <iostream>
using namespace std;

class Fruit {
public:
  virtual void printClassName() const throw() = 0;
  virtual ~Fruit() throw();
};

Fruit::~Fruit() throw()
{ }

class Apple : public Fruit {
public:
  virtual void printClassName() const throw();
};

void Apple::printClassName() const throw()
{ cout << "Apple/n"; }

class Banana : public Fruit {
public:
  virtual void printClassName() const throw();
};

void Banana::printClassName() const throw()
{ cout << "Banana/n"; }

The following BagOfFruit class allows insertion and removal of objects of any kind-of Fruit.

class Full  { };
class Empty { };

class BagOfFruit {
public:
  BagOfFruit() throw();
  unsigned size() const throw();
  void insert(Fruit& f) throw(Full);
  Fruit& remove() throw(Empty);
protected:
  enum     { maxSize_ = 20 };
  unsigned   size_;
  Fruit*     data_[maxSize_];
};

BagOfFruit::BagOfFruit() throw()
: size_(0) { }

unsigned BagOfFruit::size() const throw()
{ return size_; }

void BagOfFruit::insert(Fruit& f) throw(Full)
{
  if (size_ == maxSize_) throw Full();
  data_[size_++] = &f;
}

Fruit& BagOfFruit::remove() throw(Empty)
{
  if (size_ == 0) throw Empty();
  return *data_[--size_];
}

        下面证明了一个多态函数将任何种类的Fruit放到任何种类的BagOfFruit中去.注意.既然BagOfFruit类能担保接受所有种类的水果那么bag.insert()是正确的

void insertFruitIntoBag(BagOfFruit& bag, Fruit& fruit)
{
  bag.insert(fruit);
}

        下面的BagOfApple类是 kind-of BagOfFruit.但是BagOfApple并不能替代BagOfFruit.这个类还有其他几个问题,它用了一个引用,而且隐藏了BagOfFruit::remove() 和BagOfFruit::insert(Fruit&).

class BagOfApple : public BagOfFruit {
public:
  BagOfApple() throw();
  void insert(Apple& a) throw(Full);
  Apple& remove() throw(Empty);
};

BagOfApple::BagOfApple() throw()
: BagOfFruit()
{ }

void BagOfApple::insert(Apple& a) throw(Full)
{ BagOfFruit::insert(a); }

Apple& BagOfApple::remove() throw(Empty)
{ return (Apple&) BagOfFruit::remove(); }

        因为类BagOfApple 是继承至BagOfFruit,BagOfApple对象可以传递给insertFruitIntoBag().不幸的是,这允许毫无意义的包和水果的组合传递给insertFruitIntoBag().例如,banana可以被放入到BagofApples.

int main()
{
  BagOfApple bagOfApple;
  Banana banana;
  insertFruitIntoBag(bagOfApple, banana);

  cout << "Removing an Apple from bagOfApple: ";
  Apple& a2 = bagOfApple.remove();
  a2.printClassName();
}

 

"Removing an Apple from bagOfApple: Banana"

 

    在remove()中的指针(引用)很另人烦,但是真正的问题在于不恰当的继承.继承必须用一个严格的标准和可替代的方式来评价,因为知觉总是与事实不符.

抱歉!评论已关闭.