避免复制 switch 语句

Iva*_*ana 3 c++ boilerplate switch-statement

可以重构这段代码以避免复制 switch 语句吗?

enum class Animal
{ Cat, Dog, Fish};

float GetMaxSpeed(Animal a)
{
 switch (a)
    {
        case Animal::Cat:
            return 30;
        case Animal::Dog:
            return 40;
        case Animal::Fish:
            return 15;
    }
 }

string GetGermanTranslation(Animal a)
{
 switch (a)
    {
        case Animal::Cat:
            return "Katze";
        case Animal::Dog:
            return "Hund";
        case Animal::Fish:
            return "Fische";
    }
 }
Run Code Online (Sandbox Code Playgroud)

显然,这是一个玩具示例,我真正的枚举类要大得多。

眠りネ*_*ネロク 5

更面向对象的方法将包括依赖多态性,而不是连续切换表示类型的枚举器值。

要遵循这种方法,首先,定义一个抽象类,Animal,指定其子类应实现的成员函数:

class Animal {
public:
    virtual std::string GetGermanTranslation() const = 0;
    virtual float GetMaxSpeed() const = 0;
    virtual ~Animal() = default;
};
Run Code Online (Sandbox Code Playgroud)

然后,从此类公开派生并覆盖虚拟成员函数GetGermanTranslation()GetMaxSpeed()

例如,对于Cat

class Cat: public Animal {
public:
   std::string GetGermanTranslation() const override { return "Katze"; };
   float GetMaxSpeed() const override  { return 30; };
};
Run Code Online (Sandbox Code Playgroud)

然后,对于Dog

class Dog: public Animal {
public:
   std::string GetGermanTranslation() const override { return "Hund"; };
   float GetMaxSpeed() const override  { return 40; };
};
Run Code Online (Sandbox Code Playgroud)

您可以类似地定义Fish类。

最后,有了指向Animal对象的指针或引用,您只需调用相应的虚拟成员函数:

void displayAnimal(const Animal& animal) {
   std::cout << "The " << animal.GetGermanTranslation();
   std::cout << " runs at " << animal.GetMaxSpeed() << '\n';
}
Run Code Online (Sandbox Code Playgroud)

如您所见,不再需要打开代表用于区分不同动物的类型的枚举器。

您可以displayAnimal()使用不同的Animal对象调用此函数:

auto cat = std::make_unique<Cat>();
displayAnimal(*cat);

auto dog = std::make_unique<Dog>();
displayAnimal(*dog);
Run Code Online (Sandbox Code Playgroud)

  • @AsteroidsWithWings 这种方法遵循[开闭原则](https://en.wikipedia.org/wiki/Open%E2%80%93close_principle),而“switch”则不然。例如,假设您必须使用“鼠标”动物来**扩展**动物:使用 OOP 方法,您所需要做的就是创建一个派生自“Animal”的新类“Mouse”并覆盖相应的成员函数。另一方面,使用“switch”方法,您将必须遍历整个代码以查找所有“switch”语句,并为每个 switch 语句添加一个新的 case。 (2认同)