4

C++ では、基本クラス Packet があり、次に多くの子 APIPacket、DataIOPacket などがあります。着信パケットを格納したいのですが、タイプがわからないため、これを変数に格納します。

Packet packet;
packet = DataIOPacket();

しかし、現在 DataIOPacket には関数 getAnalogData(); があります。私はできません:

packet.getAnalogData();

パケットにはこの機能がないため。Javaでは、パケットに格納されているオブジェクトの実際のタイプが失われないため、これが可能だと思います(これは正しいですか?)。しかし、C++ では、私の DataIOPacket は Packed に絞り込まれ、Packet で宣言されていない関数が失われます。

すべての子のすべての関数に対して、Packet で仮想関数を作成できます。しかし、私にとってこれは、ほとんどの場合呼び出されるべきではない Packet の多くの関数を意味します。APIPacket で getAnalogData() を呼び出しても意味がありません。

この問題はどのように解決されますか? 答えは見つけられませんが、多くの人がそれに遭遇しなければならないと感じています。

DataIOPacket と APIPacket への型キャストで何かを行うこともできますが、これも実際にはクリーンなソリューションではないようです。

私の問題を解決するライブラリはありますか?

Rgds、

ロエル

4

3 に答える 3

4

これは Java や C++ でも可能です。タイプを確認するには、dynamic_cast を実行する必要があります。

 Packet* packet;
packet = new DataIOPacket();

      DataIOPacket dio* = dynamic_cast<DataIOPacket*>(packet); 
            if (dio != 0)
            {
             dio->DoSomeChildMethodStuff();
            }
于 2013-03-14T16:51:33.027 に答える
1

C++ では、 myDataIOPacketは a に狭められ、Packet宣言されていない関数が失われますPacket

DataIOPacketこれは、 type のオブジェクトを type のオブジェクトに割り当てたPacket結果、このオブジェクトがスライスされたために発生します (オブジェクトのスライスとは?を参照してください)。

実際に探しているのは、作業しているオブジェクトが のインスタンスとして作成されているかどうかを実行時DataIOPacketに確認する方法です。つまり、 Run-Time Type Identification (RTTI)を探しているということです。

スライスを回避するには、オブジェクトへの参照またはポインターが必要です。このオブジェクトのタイプは、実行時に識別されます。

Packet* packet;
packet = new DataIOPacket();

現在packetは型DataIOPacket( run-time ) のオブジェクトへのポインターですが、ポインターの型はPacket*( compile time ) です。このオブジェクトのクラスに固有のメソッドを呼び出すためにDataIOPacket、コンパイラは、このポインターがそのメソッドを提供するタイプのオブジェクトを指していることを知る必要があります。ポインターをポリモーフィック型にダウンキャストする適切な方法は、 を使用することです。これは、このオブジェクトをこの型にキャストできない場合dynamic_castに返されます。NULL

Packet* packet;
packet = new DataIOPacket();
DataIOPacket* dataIOPacket = dynamic_cast<DataIOPacket*>(packet);
if (dataIOPacket)
    dataIOPacket->getAnalogData();

これは、自動保存期間を持つオブジェクトでも可能であることに注意してください。

DataIOPacket packet;
Packet* pPacket = &packet;

DataIOPacket* dataIOPacket = dynamic_cast<DataIOPacket*>(pPacket);
if (dataIOPacket)
    dataIOPacket->getAnalogData();

この場合、 のタイプは、成功packetするかどうかを決定する重要な要素です。メソッドを呼び出すには、dynamic_castオブジェクトを のインスタンスとして作成する必要があります。DataIOPacketgetAnalogData

于 2013-03-14T17:08:52.483 に答える
0

何人かの人々が示唆したように、ダイナミックキャストをしなければならないことは私の構造が間違っていることを示唆していることを私は理解しました。そこで、各タイプのパケットが独自のストレージスペースを取得するように変更します。パケットを読み込んだ場所に保存してから、すべての処理を行うメインスレッドに渡されます。確かに、タイプを保持する方が理にかなっています。私のメインスレッドは、さまざまなパケットを処理する方法が異なるため、パケットのタイプを把握したくありません。私の質問で説明した動作が必要になった場合は、動的キャストが最適だと思います。ただし、そうする前に、構造を変更するべきではないかどうかを実際に自問する必要があります。また、動的キャストの使用は、オブジェクトがスライスされているため、オブジェクトでは機能しません。ポインタでのみ機能します。

于 2013-03-14T21:05:08.527 に答える