关于c ++:类设计的选择

Choice for class design

我有一个典型的课堂设计问题,我想听听你的意见。

让我们想象一下,我有一个基础类动物。从这一类中,我衍生出几种特定的动物。我对他们之间的互动很感兴趣。由于它们之间的交互可能因动物而异,所以我所做的就是用纯虚拟函数(即抽象类)创建基类:

class dog;

class cat;

class bird;

class Animal{

private:

int legs;

public:

virtual void Interact(const dog &) = 0;

virtual void Interact(const cat &) = 0;

virtual void Interact(const bird &) = 0;

};

然后,对于每个特定的动物,我从动物类创建一个派生类。例如:

class dog: public Animal{

// Implementation of interaction with other animals:

void Interact(const dog & object) {...body...};

void Interact(const cat & object) {...body...};

void Interact(const bird & object) {...body...};

};

类似于猫和鸟的课程。现在我关心的是鸟类课程。鸟类可以飞行,并有狗和猫没有的额外变量/方法。什么是一个聪明的方法来管理它?例如,一种蛮力的方法是向基础类动物添加额外的方法和变量,如int wingsvoid fly()。关键是狗和猫类不会使用它们。它不干净。另一种方法可能是声明一个派生类flyinganimal from animal:

class FlyingAnimal: public Animal{

private:

int wings;

public:

void Fly();

};

然后我可以用这只鸟而不是动物来创造类鸟:

class Bird: public FlyingAnimal{

body and definition of void Interact(...)...

};

你觉得怎么样?也许你还有别的建议。

非常感谢!XDOF


当你只有三个班时,对其他可能的动物使用不同的交互方法是可行的,但是当你添加老鼠、兔子、老虎、老鼠、附魔、袋熊、海豚、犰狳和斑马时,它会很快变得笨拙,因为每当你添加一个新的动物时,你需要编辑每个现有的班来添加一个新的交互方法。这不是面向对象编程的方式。OOP的目的是您可以简单地添加一个新类,并且所有其他类都可以立即使用它,而不需要任何修改。

出于这个原因,您应该以更一般化的方式处理交互。为什么猫猎杀老鼠或鸟,而不是狗?当我面对一只带着微笑的猫时会发生什么?(笑是一种小的、毛绒绒绒的、四条腿的、食草的哺乳动物,大约5厘米长,我刚刚编了一个class Smibblat: public Animal来代替它)。即使这只猫以前从来没有见过一个微笑,它也会试图去猎杀它,因为它符合它的猎物模式。猫对所有1岁的动物都是危险的。更小和2。比他们自己慢。

当您将一个抽象的getSize()和一个抽象的getSpeed()方法添加到类动物中时,您可以使用如下方法:

1
2
3
4
5
6
void Cat::interact(const Animal & other) {
     if (other.getSpeed() < this.getSpeed() &&
         other.getSize() < this.getSize()) {
         this.eat(other);
     }
}

它可以应用于你创造的任何新动物。猫类将不再依赖于其他所有的动物子类。它只取决于动物,它提供了决定是否吃其他动物的所有重要方法。


我认为你做错的第一件事是在基类的接口中有派生类。你应该使用访客模式。您可以为三个动物类创建通用交互访问者或三个单独的访问者。然后提供要作为构造函数参数进行交互的动物。