IDが0、1、2、3、...になると仮定すると、std::map
各メッセージIDを、そのIDに適切な種類のオブジェクトを作成する名前付きコンストラクターへの関数ポインターにマップするを作成できます。
class BaseClass {
private:
typedef (BaseClass*) (*NamedConstructor) (SomeType &);
// The map.
static std::map<int, NamedConstructor> id_to_constructor;
public:
// All the possible message types.
enum MessageType {
FooMsg = some_value,
BarMsg = some_other_value,
... // potentially a whole lot more
};
// Add a named constructor to the map.
static void add_handler (MessageType id, NamedConstructor cotr) {
// Error handling such as duplicates left as an exercise to the user.
id_to_constructor[id] = cotr;
}
// Function that applies the map.
static void handle_message (int id, SomeType & my_file) {
// Error handling such as a missing entry left as an exercise to the user.
NamedConstructor cotr = id_to_constructor[id];
cotr (my_file);
}
...
};
class Foo : public BaseClass {
public:
static BaseClass* create_foo (SomeType & my_file) {
return new Foo (my_file); // Or use a smart pointer.
}
// Member data and member functions elided.
...
};
class Bar : public BaseClass {
public:
static BaseClass* create_bar (SomeType & my_file) {
return new Bar (my_file); // Or use a smart pointer.
}
// Member data and member functions elided.
...
};
メソッド を使用して名前付きコンストラクターなどをFoo::create_foo()
登録するには、何らかのメカニズムが必要です。500のメッセージタイプがある場合、それは500行のコードですが、直線(ifなし、スイッチなし)のコードになります。Bar::create_bar()
BaseClass
add_handler
別の方法は、500ケースのswitchステートメントです。うん。
では、なぜベクトルではなくマップなのか?IDが0、1、2、...になることがわかっている場合は、ベクトルで問題ありません。ギャップがある場合はどうなりますか?設計上、大きなギャップがある場合はどうなりますか?たとえば、メッセージIDは、エラーを減らすためにハミング符号化されている場合があります。