C++ 避免复制开关状态
可以重构此代码以避免复制switch语句吗C++ 避免复制开关状态,c++,switch-statement,boilerplate,C++,Switch Statement,Boilerplate,可以重构此代码以避免复制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: retur
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";
}
}
显然,这是一个玩具示例,我真正的枚举类要大得多。更面向对象的方法是依赖多态性,而不是连续打开表示类型的枚举数值 要遵循此方法,首先定义一个抽象类,
Animal
,该类指定其子类应实现的成员函数:
class Animal {
public:
virtual std::string GetGermanTranslation() const = 0;
virtual float GetMaxSpeed() const = 0;
virtual ~Animal() = default;
};
然后,公开从此类派生并重写虚拟成员函数GetGermanTranslation()
和GetMaxSpeed()
例如,对于Cat
:
class Cat: public Animal {
public:
std::string GetGermanTranslation() const override { return "Katze"; };
float GetMaxSpeed() const override { return 30; };
};
然后,类似地,对于狗:
class Dog: public Animal {
public:
std::string GetGermanTranslation() const override { return "Hund"; };
float GetMaxSpeed() const override { return 40; };
};
您可以类似地定义Fish
类
最后,有一个指向动物
对象的指针或引用,只需调用相应的虚拟成员函数:
void displayAnimal(const Animal& animal) {
std::cout << "The " << animal.GetGermanTranslation();
std::cout << " runs at " << animal.GetMaxSpeed() << '\n';
}
如果不另行指定,则枚举类型中的第一个枚举数的值为0,后续枚举数的值比前一个枚举数的值大一个。所以
enum Animal
{ Cat, Dog, Fish};
Cat
的值为0,Dog
的值为1,Fish
的值为2。要将这些值映射到其他值集,只需将它们用作数组索引:
int max_speed[] = {
30, 40, 15
};
const char* german_name[] = {
"Katze",
"Hund",
"Fische"
};
现在,您可以编写诸如max\u speed[Cat]
和德语名称[Dog]
之类的内容
请注意,字符串文本位于双引号内,例如,“Katze”
,而不是问题中的单引号。围绕多个字符的单引号创建了一个称为“多字符文字”的时髦东西。它们几乎毫无用处。似乎很简单。根据枚举值的数量,是否尝试简单地使用映射或数组枚举枚举枚举值,并给出相应的速度和转换?或者,如果保证枚举值在数值上是连续的,则使用两者的简单数组?不需要任何开关语句。考虑使用不同的方法:<代码> const动物数据MIATALDATABOR[] = {{动物::猫,30,“Katze”},{动物::40,“Hund”},{动物::鱼,15,“FISCHE”};<代码> >不幸的是C++不支持指定的初始化语法,<代码> [动物::猫] = { 30,“Katze”} /代码> @ USE253551。你能详细说明这个吗?最好是回答。@ SavValavik谢谢,这也是非常有用的。如果没有直接映射,例如最大速度未知,有什么解决方案吗?可以使用映射(std::map
)来过滤稀疏索引,但这似乎是一种过度使用。对于某些情况下可能缺少的功能,可以使用std::optional
。或者您可以使用std::bitset
来跟踪现有的功能。这太过分了。我举了一个例子,说明如何不这样做。这种开关非常简单、快速,并且易于维护。而且你的解是正交的;OP具有枚举值而不是事物的实例。@swiths此方法遵循,而开关不遵循。例如,假设您必须使用鼠标动物扩展动物:使用OOP方法,您只需创建一个新类mouse
,该类派生自animal
,并重写相应的成员函数。另一方面,使用switch
方法,您必须遍历整个代码,查找所有switch
语句,并为每个switch语句添加一个新的大小写。多态方法可以在不修改现有代码的情况下进行扩展,然而,基于switch
语句的方法需要修改现有代码以进行扩展。后者不仅要做更多的工作,而且更容易出错。它也不太本地化,并且在整个代码中传播。不正确。编译器警告交换机中缺少枚举。这是一项非常非常小的工作。这是一个非常有用的问题,但在我的现实世界中,我希望在枚举及其属性之间有明确的、可读的映射。
int max_speed[] = {
30, 40, 15
};
const char* german_name[] = {
"Katze",
"Hund",
"Fische"
};