21天学C++(十四)多态性

完整目录、平台简介、安装环境及版本:参考《21天学C++ 概览》

十四、多态性

14.1 单一继承问题

以下两种情况:

  • Pegasus需要把Bird中的Fly()函数复制过来,不利于维护;
  • 如果哪天Horse突然想飞了,还需要把Fly()函数从Pegasus移动到Horse中;

14.1.1 升迁

将所需要的函数放到较高的类层次,及升迁到基类中,所有派生类都能使用,但容易使基类庞杂;

一般来说,将派生类共享的功能有选择地升迁到基类中,而不是迁移所有派生类的接口;

如Horse和Bird有一个共享的基类Animal,且Horse和Bird有一个公有的功能eat,则可以将eat放到接类Animal中;但是想Fly()这种只有Bird才有的,就应该避免升迁到基类中;

14.1.2 下降

将非共享功能放在派生类中,当指针实际指向派生类对象时才调用;

使用RTTI(运行类型 鉴定Runtime Type Identification )判断指针实际指向类型;

函数为了调用Fly(),需要告诉指针是指向Pegasus而非Horse,即下降;

可以利用dynamic_cast进行判断,如果转换正确,则说明该指针正是指向转换后的类型,否则返回空;

#include <iostream>
using namespace std;

enum TYPE { HORSE, PEGASUS };

class Horse
{
public:
	virtual void Gallop(){ cout << "Galloping...\n"; }

private:
	int itsAge;
};

class Pegasus : public Horse
{
public:
	virtual void Fly()
	{cout<<"I can fly! I can fly! I can fly!\n";}
};

const int NumberHorses = 5;
int main()
{
	Horse* Ranch[NumberHorses];
	Horse* pHorse;
	int choice,i;
	for (i=0; i<NumberHorses; i++)
	{
		cout << "(1)Horse (2)Pegasus: ";
		cin >> choice;
		if (choice == 2)
			pHorse = new Pegasus;
		else
			pHorse = new Horse;
		Ranch[i] = pHorse;
	}
	cout << endl;
	for (i=0; i<NumberHorses; i++)
	{
		Pegasus *pPeg = dynamic_cast< Pegasus *> (Ranch[i]);
		if (pPeg != NULL)
			pPeg->Fly();
		else
			cout << "Just a horse\n";

		delete Ranch[i];
	}
	return 0;
}

执行结果如下:

(1)Horse (2)Pegasus: 1
(1)Horse (2)Pegasus: 2
(1)Horse (2)Pegasus: 3
(1)Horse (2)Pegasus: 4
(1)Horse (2)Pegasus: 1

Just a horse
I can fly! I can fly! I can fly!
Just a horse
Just a horse
Just a horse
请按任意键继续. . .

14.2 多重继承

14.2.1 多重继承:从多个基类中派生一个新类

类声明中,需要用逗号将多个基类分开

#include <iostream>
using std::cout;
using std::cin;
using std::endl;

class Horse
{
public:
	Horse() { cout << "Horse constructor... "; }
	virtual ~Horse() { cout << "Horse destructor... "; }
	virtual void Whinny() const { cout << "Whinny!... "; }
private:
	int itsAge;
};

class Bird
{
public:
	Bird() { cout << "Bird constructor... "; }
	virtual ~Bird() { cout << "Bird destructor... "; }
	virtual void Chirp() const { cout << "Chirp... ";  }
	virtual void Fly() const
	{
		cout << "I can fly!";
	}
private:
	int itsWeight;
};

class Pegasus : public Horse, public Bird
{
public:
	void Chirp() const { Whinny(); }
	Pegasus() { cout << "Pegasus constructor... "; }
	~Pegasus() { cout << "Pegasus destructor...  "; }
};

const int MagicNumber = 2;
int main()
{
	Horse* Ranch[MagicNumber];
	Bird* Aviary[MagicNumber];
	Horse * pHorse;
	Bird * pBird;
	int choice,i;
	for (i=0; i<MagicNumber; i++)
	{
		cout << "\n(1)Horse (2)Pegasus: ";
		cin >> choice;
		if (choice == 2)
			pHorse = new Pegasus;
		else
			pHorse = new Horse;
		Ranch[i] = pHorse;
	}
	for (i=0; i<MagicNumber; i++)
	{
		cout << "\n(1)Bird (2)Pegasus: ";
		cin >> choice;
		if (choice == 2)
			pBird = new Pegasus;
		else
			pBird = new Bird;
		Aviary[i] = pBird;
	}

	cout << endl;
	for (i=0; i<MagicNumber; i++)
	{
		cout << "\nRanch[" << i << "]: " ;
		Ranch[i]->Whinny();
		delete Ranch[i];
	}

	for (i=0; i<MagicNumber; i++)
	{
		cout << "\nAviary[" << i << "]: " ;
		Aviary[i]->Chirp();
		cout<<endl;
		Aviary[i]->Fly();
		delete Aviary[i];
	}
	cout<<endl;
	return 0;
}

执行结果如下:

(1)Horse (2)Pegasus: 1
Horse constructor...
(1)Horse (2)Pegasus: 2
Horse constructor... Bird constructor... Pegasus constructor...
(1)Bird (2)Pegasus: 3
Bird constructor...
(1)Bird (2)Pegasus: 1
Bird constructor...

Ranch[0]: Whinny!... Horse destructor...
Ranch[1]: Whinny!... Pegasus destructor...  Bird destructor... Horse destructor...
Aviary[0]: Chirp...
I can fly!Bird destructor...
Aviary[1]: Chirp...
I can fly!Bird destructor...
请按任意键继续. . .

14.2.2 多重继承构造函数初始化

依次初始化构造函数

#include <iostream>
using namespace std;

typedef int HANDS;
enum COLOR { Red, Green, Blue, Yellow, White, Black, Brown } ;

class Horse
{
public:
	Horse(COLOR color, HANDS height);
	virtual ~Horse() { cout << "Horse destructor..." << endl; }
	virtual void Whinny()const { cout << "Whinny!... "; }
	virtual HANDS GetHeight() const { return itsHeight; }
	virtual COLOR GetColor() const { return itsColor; }
private:
	HANDS itsHeight;
	COLOR itsColor;
};

Horse::Horse(COLOR color, HANDS height):
itsColor(color),itsHeight(height)
{
	cout << "Horse constructor..." << endl;
}

class Bird
{
public:
	Bird(COLOR color, bool migrates);
	virtual ~Bird() {cout << "Bird destructor..." << endl;  }
	virtual void Chirp()const { cout << "Chirp... ";  }
	virtual void Fly()const
	{
		cout << "I can fly! I can fly! I can fly! ";
	}
	virtual COLOR GetColor()const { return itsColor; }
	virtual bool GetMigration() const { return itsMigration; }

private:
	COLOR itsColor;
	bool itsMigration;
};

Bird::Bird(COLOR color, bool migrates):
itsColor(color), itsMigration(migrates)
{
	cout << "Bird constructor..." << endl;
}

class Pegasus : public Horse, public Bird
{
public:
	void Chirp()const { Whinny(); }
	Pegasus(COLOR, HANDS, bool,long);
	~Pegasus() {cout << "Pegasus destructor..." << endl;}
	virtual long GetNumberBelievers() const
	{
		return  itsNumberBelievers;
	}

private:
	long itsNumberBelievers;
};

Pegasus::Pegasus(
				 COLOR aColor,
				 HANDS height,
				 bool migrates,
				 long NumBelieve):
Horse(aColor, height),
Bird(aColor, migrates),
itsNumberBelievers(NumBelieve)
{
	cout << "Pegasus constructor..." << endl;
}

int main()
{
	Pegasus *pPeg = new Pegasus(Red, 5, true, 10);
	pPeg->Fly();
	pPeg->Whinny();
	cout << "\nYour Pegasus is " << pPeg->GetHeight();
	cout << " hands tall and ";
	if (pPeg->GetMigration())
		cout << "it does migrate.";
	else
		cout << "it does not migrate.";
	cout << "\nA total of " << pPeg->GetNumberBelievers();
	cout << " people believe it exists." << endl;
	delete pPeg;
	return 0;
}

执行结果如下:

Horse constructor...
Bird constructor...
Pegasus constructor...
I can fly! I can fly! I can fly! Whinny!...
Your Pegasus is 5 hands tall and it does migrate.
A total of 10 people believe it exists.
Pegasus destructor...
Bird destructor...
Horse destructor...
请按任意键继续. . .

14.2.3 歧义解析1

当多个基类存在同样函数时,派生类调用该函数就会存在歧义

  • 如:pPeg->GetColor();
  • 编译器将会报错,因为Horse和Bird均有GetColor函数,对编译器会产生歧义;
  • 需要明确指定:pPeg->Horse::GetColor();
class Horse{
  public:
    virtual COLOR GetColor() const { return itsColor; }
};
class Bird{
  public:
    virtual COLOR GetColor()const { return itsColor; }
};
class Pegasus : public Horse, public Bird{};

int main(){
   Pegasus *pPeg = new Pegasus(Red, 5, true, 10);
   delete pPeg;
   return 0;
}

14.2.4 歧义解析2

砖石型继承:

  • 歧义1中,把共有函数上升到基类中;
  • 基类Animal提供关于年龄的GetAge函数;
  • 派生类Bird和Horse继承了基类Animal;
  • 派生类Pegasus又从Bird和Horse继承;
  • 派生类Pegasus对象会产生两个Animal副本;

模糊问题:Pegasus对象调用GetAge函数时,是通过Horse还是Bird调用Animal函数?
需要明确指定:virtual int GetAge() const { return Horse::GetAge(); }

class Animal{
  public:
    virtual int GetAge() const { return itsAge; }
};
class Horse : public Animal{
};
class Bird : public Animal{
};
class Pegasus : public Horse, public Bird{
    // virtual int GetAge() const { return Horse::GetAge(); }
  private:
    long itsNumberBelievers;
};
int main(){
   Pegasus *pPeg = new Pegasus(Red, 5, true, 10, 2);
   delete pPeg;
   return 0;
}
#include <iostream>
using namespace std;

typedef int HANDS;
enum COLOR { Red, Green, Blue, Yellow, White, Black, Brown } ;

class Animal        // common base to both horse and bird
{
public:
	Animal(int);
	virtual ~Animal() { cout << "Animal destructor...\n"; }
	virtual int GetAge() const { return itsAge; }
	virtual void SetAge(int age) { itsAge = age; }
private:
	int itsAge;
};

Animal::Animal(int age):itsAge(age)
{
	cout << "Animal constructor...\n";
}

class Horse : public Animal
{
public:
	Horse(COLOR color, HANDS height, int age);
	virtual ~Horse() { cout << "Horse destructor...\n"; }
	virtual void Whinny()const { cout << "Whinny!... "; }
	virtual HANDS GetHeight() const { return itsHeight; }
	virtual COLOR GetColor() const { return itsColor; }
protected:
	HANDS itsHeight;
	COLOR itsColor;
};

Horse::Horse(COLOR color, HANDS height, int age):Animal(age),itsColor(color),itsHeight(height)
{
	cout << "Horse constructor...\n";
}

class Bird : public Animal
{
public:
	Bird(COLOR color, bool migrates, int age);
	virtual ~Bird() {cout << "Bird destructor...\n";  }
	virtual void Chirp()const { cout << "Chirp... ";  }
	virtual void Fly()const
	{ cout << "I can fly! I can fly! I can fly! "; }
	virtual COLOR GetColor()const { return itsColor; }
	virtual bool GetMigration() const { return itsMigration; }
protected:
	COLOR itsColor;
	bool itsMigration;
};

Bird::Bird(COLOR color, bool migrates, int age):Animal(age),itsColor(color), itsMigration(migrates)
{
	cout << "Bird constructor...\n";
}

class Pegasus : public Horse, public Bird
{
public:
	void Chirp()const { Whinny(); }
	Pegasus(COLOR, HANDS, bool, long, int);
	virtual ~Pegasus() {cout << "Pegasus destructor...\n";}
	virtual long GetNumberBelievers() const
	{ return  itsNumberBelievers; }
	virtual COLOR GetColor()const { return Horse::itsColor; }
	virtual int GetAge() const { return Horse::GetAge(); }
private:
	long itsNumberBelievers;
};

Pegasus::Pegasus(COLOR aColor,
				 HANDS height,
				 bool migrates,
				 long NumBelieve,
				 int age):Horse(aColor, height,age),Bird(aColor, migrates,age),itsNumberBelievers(NumBelieve)
{
	cout << "Pegasus constructor...\n";
}

int main()
{
	Pegasus *pPeg = new Pegasus(Red, 5, true, 10, 2);
	int age = pPeg->GetAge();
	cout << "This pegasus is " << age << " years old.\n";
	delete pPeg;
	return 0;
}

执行结果如下:

Animal constructor...
Horse constructor...
Animal constructor...
Bird constructor...
Pegasus constructor...
This pegasus is 2 years old.
Pegasus destructor...
Bird destructor...
Animal destructor...
Horse destructor...
Animal destructor...
请按任意键继续. . .

14.2.5 虚继承

砖石型继承,即只有一个Animal副本,这样就不会产生歧义;

  • 通常类构造函数只初始化自己的变量和基类;
  • 虚继承是个例外,由最强派生类初始化;即Animal不由Bird和Horse初始化,而是由Pegasus初始化。
  • Bird和Horse必须在其构造函数内初始化Animal,但创建Pegasus对象时,这些初始化将被忽略
#include <iostream>
using namespace std;

typedef int HANDS;
enum COLOR { Red, Green, Blue, Yellow, White, Black, Brown } ;

class Animal        // common base to both horse and bird
{
public:
	Animal(int);
	virtual ~Animal() { cout << "Animal destructor...\n"; }
	virtual int GetAge() const { return itsAge; }
	virtual void SetAge(int age) { itsAge = age; }
private:
	int itsAge;
};

Animal::Animal(int age):
itsAge(age)
{
	cout << "Animal constructor...\n";
}

class Horse : virtual public Animal
{
public:
	Horse(COLOR color, HANDS height, int age);
	virtual ~Horse() { cout << "Horse destructor...\n"; }
	virtual void Whinny()const { cout << "Whinny!... "; }
	virtual HANDS GetHeight() const { return itsHeight; }
	virtual COLOR GetColor() const { return itsColor; }
protected:
	HANDS itsHeight;
	COLOR itsColor;
};

Horse::Horse(COLOR color, HANDS height, int age):
Animal(age),
itsColor(color),itsHeight(height)
{
	cout << "Horse constructor...\n";
}

class Bird : virtual public Animal
{
public:
	Bird(COLOR color, bool migrates, int age);
	virtual ~Bird() {cout << "Bird destructor...\n";  }
	virtual void Chirp()const { cout << "Chirp... ";  }
	virtual void Fly()const
	{ cout << "I can fly! I can fly! I can fly! "; }
	virtual COLOR GetColor()const { return itsColor; }
	virtual bool GetMigration() const { return itsMigration; }
protected:
	COLOR itsColor;
	bool itsMigration;
};

Bird::Bird(COLOR color, bool migrates, int age):
Animal(age),
itsColor(color), itsMigration(migrates)
{
	cout << "Bird constructor...\n";
}

class Pegasus : public Horse, public Bird
{
public:
	void Chirp()const { Whinny(); }
	Pegasus(COLOR, HANDS, bool, long, int);
	virtual ~Pegasus() {cout << "Pegasus destructor...\n";}
	virtual long GetNumberBelievers() const
	{ return  itsNumberBelievers; }
	virtual COLOR GetColor()const { return Horse::itsColor; }
private:
	long itsNumberBelievers;
};

Pegasus::Pegasus(
				 COLOR aColor,
				 HANDS height,
				 bool migrates,
				 long NumBelieve,
				 int age):
Horse(aColor, height,age),
Bird(aColor, migrates,age),
Animal(age*2),
itsNumberBelievers(NumBelieve)
{
	cout << "Pegasus constructor...\n";
}

int main()
{
	Pegasus *pPeg = new Pegasus(Red, 5, true, 10, 2);
	int age = pPeg->GetAge();
	cout << "This pegasus is " << age << " years old.\n";
	delete pPeg;
	return 0;
}

执行结果如下:

Animal constructor...
Horse constructor...
Bird constructor...
Pegasus constructor...
This pegasus is 4 years old.
Pegasus destructor...
Bird destructor...
Horse destructor...
Animal destructor...
请按任意键继续. . .

14.2.6 多重继承存在的问题

很多编译器不支持,调试很困难;

多重继承可以通过其他方式实现;

建议:

  • 当一个新类需要从多个基类中继承函数和特征时必须用多重继承;
  • 当派生类最强的类必须只有共享基类的一个实例时必须用虚继承;
  • 当用虚基类时一定要初始化派生性最强哦类的共享基类;

不建议:

  • 在用单一继承可以实现目的的情况下,不要用多重继承;

14.3 抽象数据类型

Shape是一个抽象类,不能初始化,试图实例化会很麻烦;
Shape存在的目的仅仅是为从Shape中派生的类提供一个接口,称之为抽象数据类型或ADT;

抽象数据类型代表的是一个概念而非一个对象;
C++中,一个ADT总是其他类的基类,生成ADT的实例是非法的。

#include <iostream>
using std::cout;
using std::cin;
using std::endl;

class Shape
{
public:
	Shape(){}
	virtual ~Shape(){}
	virtual long GetArea() { return -1; } // error
	virtual long GetPerim() { return -1; }
	virtual void Draw() {}
private:
};

class Circle : public Shape
{
public:
	Circle(int radius):itsRadius(radius){}
	~Circle(){}
	long GetArea() { return 3 * itsRadius * itsRadius; }
	long GetPerim() { return 6 * itsRadius; }
	void Draw();
private:
	int itsRadius;
	int itsCircumference;
};

void Circle::Draw()
{
	cout << "Circle drawing routine here!\n";
}


class Rectangle : public Shape
{
public:
	Rectangle(int len, int width):
	  itsLength(len), itsWidth(width){}
	  virtual ~Rectangle(){}
	  virtual long GetArea() { return itsLength * itsWidth; }
	  virtual long GetPerim() {return 2*itsLength + 2*itsWidth; }
	  virtual int GetLength() { return itsLength; }
	  virtual int GetWidth() { return itsWidth; }
	  virtual void Draw();
private:
	int itsWidth;
	int itsLength;
};

void Rectangle::Draw()
{
	for (int i = 0; i<itsLength; i++)
	{
		for (int j = 0; j<itsWidth; j++)
			cout << "x ";

		cout << "\n";
	}
}

class Square : public Rectangle
{
public:
	Square(int len);
	Square(int len, int width);
	~Square(){}
	long GetPerim() {return 4 * GetLength();}
};

Square::Square(int len):
Rectangle(len,len)
{}

Square::Square(int len, int width):
Rectangle(len,width)
{
	if (GetLength() != GetWidth())
		cout << "Error, not a square... a Rectangle??\n";
}

int main()
{
	Shape *s = new Shape();

	int choice;
	bool fQuit = false;
	Shape * sp;

	while ( !fQuit )
	{
		cout << "(1)Circle (2)Rectangle (3)Square (0)Quit: ";
		cin >> choice;

		switch (choice)
		{
		case 0:   fQuit = true;
			break;
		case 1: sp = new Circle(5);
			break;
		case 2: sp = new Rectangle(4,6);
			break;
		case 3: sp = new Square(5);
			break;
		default: 
			cout <<"Please enter a number between 0 and 3"<<endl;
			continue;
			break;
		}
		if( !fQuit )
			sp->Draw();
		delete sp;
		sp = 0;
		cout << endl;
	}
	return 0;
}

执行结果如下:

(1)Circle (2)Rectangle (3)Square (0)Quit: 1
Circle drawing routine here!

(1)Circle (2)Rectangle (3)Square (0)Quit: 2
x x x x x x
x x x x x x
x x x x x x
x x x x x x

(1)Circle (2)Rectangle (3)Square (0)Quit: 3
x x x x x
x x x x x
x x x x x
x x x x x
x x x x x

(1)Circle (2)Rectangle (3)Square (0)Quit: 0

请按任意键继续. . .

14.3.1 纯虚函数

C++支持用纯虚函数来创建抽象数据类型ADT,一个虚函数通过初始化为0就变成纯虚函数;

实例化ADT,编译器会报错,ADT意味着:

  • 不用从这个类中创建对象,要从其中派生;
  • 确信覆盖了纯虚函数;

任何一个从ADT派生的类,必须覆盖每一个纯虚函数;

class Shape{
  public:
     Shape(){}
     ~Shape(){}
     virtual long GetArea() = 0;//纯虚函数
     virtual long GetPerim()= 0; //纯虚函数
     virtual void Draw() = 0; //纯虚函数
};

14.3.2 实现纯虚函数

一般来说,不用实现抽象基类ADT中的纯虚函数;

可以给纯虚函数提供一个实现代码,这个函数可以被ADT继承的对象所调用,这样做的目的可能是为了给所有覆盖的函数提供公共功能;

#include <iostream>
using namespace std;

enum COLOR { Red, Green, Blue, Yellow, White, Black, Brown } ;

class Animal        // common base to both Mammal and Fish
{
public:
	Animal(int);
	virtual ~Animal() { cout << "Animal destructor...\n"; }
	virtual int GetAge() const { return itsAge; }
	virtual void SetAge(int age) { itsAge = age; }
	virtual void Sleep() const = 0;
	virtual void Eat() const = 0;
	virtual void Reproduce() const = 0;
	virtual void Move() const = 0;
	virtual void Speak() const = 0;
private:
	int itsAge;
};

Animal::Animal(int age):
itsAge(age)
{
	cout << "Animal constructor...\n";
}

class Mammal : public Animal
{
public:
	Mammal(int age):Animal(age)
	{ cout << "Mammal constructor...\n";}
	virtual ~Mammal() { cout << "Mammal destructor...\n";}
	virtual void Reproduce() const
	{ cout << "Mammal reproduction depicted...\n"; }
};

class Fish : public Animal
{
public:
	Fish(int age):Animal(age)
	{ cout << "Fish constructor...\n";}
	virtual ~Fish() {cout << "Fish destructor...\n";  }
	virtual void Sleep() const { cout << "fish snoring...\n"; }
	virtual void Eat() const { cout << "fish feeding...\n"; }
	virtual void Reproduce() const
	{ cout << "fish laying eggs...\n"; }
	virtual void Move() const
	{ cout << "fish swimming...\n";   }
	virtual void Speak() const { }
};

class Horse : public Mammal
{
public:
	Horse(int age, COLOR color ):
	  Mammal(age), itsColor(color)
	  { cout << "Horse constructor...\n"; }
	  virtual ~Horse() { cout << "Horse destructor...\n"; }
	  virtual void Speak()const { cout << "Whinny!... \n"; }
	  virtual COLOR GetItsColor() const { return itsColor; }
	  virtual void Sleep() const
	  { cout << "Horse snoring...\n"; }
	  virtual void Eat() const { cout << "Horse feeding...\n"; }
	  virtual void Move() const { cout << "Horse running...\n";}

protected:
	COLOR itsColor;
};

class Dog : public Mammal
{
public:
	Dog(int age, COLOR color ):
	  Mammal(age), itsColor(color)
	  { cout << "Dog constructor...\n"; }
	  virtual ~Dog() { cout << "Dog destructor...\n"; }
	  virtual void Speak()const { cout << "Whoof!... \n"; }
	  virtual void Sleep() const { cout << "Dog snoring...\n"; }
	  virtual void Eat() const { cout << "Dog eating...\n"; }
	  virtual void Move() const  { cout << "Dog running...\n"; }
	  virtual void Reproduce() const
	  { cout << "Dogs reproducing...\n"; }

protected:
	COLOR itsColor;
};

int main()
{
	Animal *pAnimal=0;
	int choice;
	bool fQuit = false;

	while (fQuit == false)
	{
		cout << "(1)Dog (2)Horse (3)Fish (0)Quit: ";
		cin >> choice;

		switch (choice)
		{
		case 1: pAnimal = new Dog(5,Brown);
			break;
		case 2: pAnimal = new Horse(4,Black);
			break;
		case 3: pAnimal = new Fish (5);
			break;
		default: fQuit = true;
			break;
		}
		if (fQuit == false)
		{   
			pAnimal->Speak();
			pAnimal->Eat();
			pAnimal->Reproduce();
			pAnimal->Move();
			pAnimal->Sleep();
			delete pAnimal;
			cout << endl;
		}  
	}
	return 0;
}

执行结果如下:

(1)Dog (2)Horse (3)Fish (0)Quit: 1
Animal constructor...
Mammal constructor...
Dog constructor...
Whoof!...
Dog eating...
Dogs reproducing...
Dog running...
Dog snoring...
Dog destructor...
Mammal destructor...
Animal destructor...

(1)Dog (2)Horse (3)Fish (0)Quit: 2
Animal constructor...
Mammal constructor...
Horse constructor...
Whinny!...
Horse feeding...
Mammal reproduction depicted...
Horse running...
Horse snoring...
Horse destructor...
Mammal destructor...
Animal destructor...

(1)Dog (2)Horse (3)Fish (0)Quit: 3
Animal constructor...
Fish constructor...
fish feeding...
fish laying eggs...
fish swimming...
fish snoring...
Fish destructor...
Animal destructor...

(1)Dog (2)Horse (3)Fish (0)Quit: 0
请按任意键继续. . .

发表回复