gpt4 book ai didi

c++ - 多态枚举

转载 作者:搜寻专家 更新时间:2023-10-31 01:54:16 26 4
gpt4 key购买 nike

多态枚举?

In C++, we often use polymorphism to allow old code to handle new code--for instance, as long as we subclass the interface expected by a function, we can pass in the new class and expect it to work correctly with the code that was written before the new class ever existed. Unfortunately, with enums, you can't really do this, even though there are occasional times you'd like to. (For instance, if you were managing the settings for your program and you stored all of them as enum values, then it might be nice to have an enum, settings_t, from which all of your other enums inherited so that you could store every new enum in the settings list. Note that since the list contains values of different types, you can't use templates.)

If you need this kind of behavior, you're forced to store the enums as integers and then retrieve them using typecasts to assign the particular value to the setting of interest. And you won't even get the benefit of dynamic_cast to help you ensure that the cast is safe--you'll have to rely on the fact that incorrect values cannot be stored in the list.

我引用自 C++ programming tutorial .

谁能更深入地解释一下多态枚举的工作原理?如果我有模板?

最佳答案

简单地说,一个enum只是一个命名常量值,例如:

enum Settings
{
setting_number_0,
setting_number_1,
setting_number_2,
};

在上面的例子中,setting_number_X只是值 X 的命名常量,因为枚举值从 0 开始并单调递增。

然后在某种类型的容器中保留这些提供整数的基本存储类型,但仍然可以是某种类型安全的。

std::vector<Setting> app_settings;

// this works
app_settings.push_back(setting_number_0);

// this is a compile time failure, even though the underlying storage
// type for Setting is an integral value. This keeps you from adding
// invalid settings types to your container (like 13 here)
app_settings.push_back(13);

// but you also cannot (directly) add valid setting values (like 1)
// as an integral, this is also a compile time failure.
app_settings.push_back(1);

现在,假设您想添加额外的特定设置类型并将它们全部保存在一个容器中。

enum DisplaySettings
{
// ...
};

enum EngineSettings
{
// ...
};

现在,如果您想将所有设置保存在一个容器中,您就不能安全地。您可以将所有整数值存储在 std::vector<int> 的容器中或类似的,但这会导致您无法确定哪些整数类型属于哪些设置枚举。此外,由于类型不同,您不能将它们存储在一个类型安全的容器中。

解决此问题的正确方法是将设置的功能存储在容器中,如下所示:

#include <vector>
#include <iostream>

// This is our "base class" type so we can store lots of
// different setting types in our container
class setting_action
{
public:
// we enable the setting by calling our function
void enable_setting()
{
setting_function_(this);
}

protected:
// This is a function pointer, and we're using it to get some
// compile time polymorphism
typedef void (*setting_function_type)(setting_action* setting);

// these can only be constructed by derived types, and the derived
// type will provide the polymorhpic behavior by means of the
// above function pointer and based on the derived type's handler
setting_action(setting_function_type func)
: setting_function_(func)
{
}

public:
~setting_action()
{
}

private:
setting_function_type setting_function_;
};

// This is the derived type, and where most of the magic
// happens. This is templated on our actual setting type
// that we define below
template <class Setting>
class templated_setting_action
: public setting_action
{
public:
templated_setting_action(Setting setting)
: setting_action(&templated_setting_action::enable_setting)
, setting_(setting)
{
}

// This function catches the "enable_setting" call from
// our base class, and directs it to the handler functor
// object that we've defined
static void enable_setting(setting_action* base)
{
templated_setting_action<Setting>* local_this =
static_cast<templated_setting_action<Setting>*>(base);

local_this->setting_();
}

private:
Setting setting_;
};

// this is just a shorthand way of creating the specialized types
template <class T>
setting_action* create_specialized_setting_action(T type)
{
return
new templated_setting_action<T>(type);
}

// Our actual settings:
// this one displays the user name
struct display_user_name
{
void operator()()
{
std::cout << "Chad.\n";
}
};

// this one displays a short welcome message
struct display_welcome_message
{
void operator()()
{
std::cout << "Ahh, the magic of templates. Welcome!\n";
}
};

// now, we can have one container for ALL our application settings

std::vector<setting_action*> app_settings;

int main()
{
// now we can add our settings to the container...
app_settings.push_back(create_specialized_setting_action(display_user_name()));
app_settings.push_back(create_specialized_setting_action(display_welcome_message()));

// and individually enable them
app_settings[0]->enable_setting();
app_settings[1]->enable_setting();

// also, need to delete each setting to avoid leaking the memory
// left as an exercise for the reader :)
return 0;
}

关于c++ - 多态枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9945117/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com