したがって、パケットのロードを計画している場合、メモリは最近の大きなコストではなく、配列はかなり高速です。また、switchステートメントに依存してジャンプテーブルを自動生成することもできないため、ジャンプテーブルのシナリオを自分で生成する方が簡単です。以下の例でわかるように、最大255パケットを想定しています。
以下の結果を得るには、抽象化が必要です。私はそれがどのように機能するかを説明するつもりはありません。
これを更新して、(id <0)の境界チェックを行う必要がある以上のパケットサイズが必要な場合は、パケットサイズを255に設定しました。(ID>長さ)。
Packets[] packets = new Packets[255];
static {
packets[0] = new Login(6);
packets[2] = new Logout(8);
packets[4] = new GetMessage(1);
packets[8] = new AddFriend(0);
packets[11] = new JoinGroupChat(7); // etc... not going to finish.
}
public void handlePacket(IncomingData data)
{
int id = data.readByte() & 0xFF; //Secure value to 0-255.
if (packet[id] == null)
return; //Leave if packet is unhandled.
packets[id].execute(data);
}
C ++でジャンプテーブルをよく使用するため、編集して、関数ポインタージャンプテーブルの例を示します。これは非常に一般的な例ですが、実行したところ、正しく動作しました。ポインタをNULLに設定する必要があることに注意してください。C++はJavaのようにこれを自動的に行いません。
#include <iostream>
struct Packet
{
void(*execute)() = NULL;
};
Packet incoming_packet[255];
uint8_t test_value = 0;
void A()
{
std::cout << "I'm the 1st test.\n";
}
void B()
{
std::cout << "I'm the 2nd test.\n";
}
void Empty()
{
}
void Update()
{
if (incoming_packet[test_value].execute == NULL)
return;
incoming_packet[test_value].execute();
}
void InitializePackets()
{
incoming_packet[0].execute = A;
incoming_packet[2].execute = B;
incoming_packet[6].execute = A;
incoming_packet[9].execute = Empty;
}
int main()
{
InitializePackets();
for (int i = 0; i < 512; ++i)
{
Update();
++test_value;
}
system("pause");
return 0;
}
また、もう1つ取り上げておきたいのは、有名なDivide and Conquerです。したがって、私の255を超える配列のアイデアは、最悪の場合のシナリオとして、ifステートメントが8以下に削減される可能性があります。
つまり、面倒で高速に管理するのが難しく、他のアプローチの方が一般的には優れていることを覚えておいてください。ただし、これは配列がそれをカットしない場合に利用されます。ユースケースと、それぞれの状況が最もうまく機能するタイミングを把握する必要があります。チェックが少ししかない場合に、これらのアプローチのいずれも使用したくないのと同じように。
If (Value >= 128)
{
if (Value >= 192)
{
if (Value >= 224)
{
if (Value >= 240)
{
if (Value >= 248)
{
if (Value >= 252)
{
if (Value >= 254)
{
if (value == 255)
{
} else {
}
}
}
}
}
}
}
}