は、enum
は単にインスタンスの名前付き定数値である。上記の例で
enum Settings
{
setting_number_0,
setting_number_1,
setting_number_2,
};
列挙値は、0から始まり、増加するように、setting_number_X
は、単に値X
ための名前付き定数であります単調に。
これを維持すると、ある種のコンテナでは整数の基本的な格納タイプが得られますが、やはり幾分タイプセーフである可能性があります。
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>
またはそれに類するコンテナに格納することはできますが、どのような積分タイプがどのような設定列挙に属しているのかを判別することができません。また、型が異なるため、単一の型の安全なコンテナに格納することはできません。私はそれが多型は、 `「ドンをenums`ことを引用したテキストから明らかだと思う
#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;
}
:
これについて移動する正しい方法は、容器の中にこのような何かを設定する機能を格納するだろうです少なくとも最も単純な意味で、仕事をする。'enum'は基本的に基本的な整数型です。多態性の 'enum'を使いたい場所であれば、テンプレートを使ったより洗練されたソリューションが得られるはずです。 – Chad
多態型列挙体はあまり意味がありません。あなたがそれらを必要と思うならば、あなたのデザインは不器用です。あなたが本当にそれらを必要とするなら、Boost.Variantは動作するはずです。 – Pubby
@Chadでは、ちょっとしたコードスニペットの例を理解しやすくなりますか? – Matteo