1

これは少し複雑な問題なので、何が起こっているのかを説明するために最善を尽くします。何かが足りない場合は、明確にするために教えてください。

片側にモジュールまたはアプリケーションが「サービス」を提供し、クライアントがこのサービスでアクションを実行できるコールバックシステムがあります(基本的には非常に基本的なIPC)。将来の参考のために、次のような定義があるとしましょう。

typedef int (*callback)(void*); // This is NOT in our code, but makes explaining easier.

installCallback(string serviceName, callback cb); // Really handled by a proper management system

sendMessage(string serviceName, void* arg); // arg = value to pass to callback

これは、構造体や組み込みなどの基本的なタイプで正常に機能します。

MI構造は次のようになります。

Device <- Disk <- MyDiskProvider

class Disk : public virtual Device
class MyDiskProvider : public Disk

プロバイダーは、ハードウェアドライバーから、ディスクイメージを処理する接着剤まで何でもかまいません。重要なのは、クラスがディスクを継承するということです。

システム内のすべての新しいディスクについて通知される「サービス」があり、ここで問題が解決されます。

void diskHandler(void *p)
{
    Disk *pDisk = reinterpret_cast<Disk*>(p); // Uh oh!

    // Remainder is not important
}

SomeDiskProvider::initialise()
{
    // Probe hardware, whatever...

    // Tell the disk system we're here!
    sendMessage("disk-handler", reinterpret_cast<void*>(this)); // Uh oh!
}

問題は、SomeDiskProviderはDiskを継承しますが、コールバックハンドラーはその型を受け取ることができないことです(コールバック関数ポインターはジェネリックでなければならないため)。

RTTIとテンプレートはここで役立ちますか?

任意の提案をいただければ幸いです。

4

3 に答える 3

1

reinterpret_cast<>some_type *との間で変換している場合は問題ありませんvoid *。ただし、多重継承を使用しているとのことでした。その場合、階層内の 1 つのクラスが別のクラスthisと同じ値を持たない可能性があります。継承ツリーをたどって正しい答えを与えるように設計されています。thisdynamic_cast<>

したがって、SomeDiskProvider両方のキャストを使用します。

SomeDiskProvider::initialise()
{
    // Gets the right value for 'this' for the Disk part of SomeDiskProvider.
    Disk *pDisk = dynamic_cast<Disk *>(this);

    // OK, since the callback converts it back to Disk *
    sendMessage("disk-handler", reinterpret_cast<void*>(this));
}

コールバックは、質問で示したとおりです。

于 2010-04-22T01:49:52.943 に答える
1

私は 100% 確実ではありませんが、T* から void* への static_cast と元のポインター型 T* への戻りが機能するはずです。私が見ているように、問題は reinterpret_cast が実際の値を変更せずにポインターの型のみを変更し、継承の場合は static_cast がオブジェクトの先頭を指すようにポインターを調整する必要があることです。

免責事項:あなたはここで言語の暗い側にいるので、それがまったく機能することを保証することはできません.

于 2010-04-21T05:23:43.647 に答える
1

あなたのコードは危険に見えます。問題は、 を にキャストしてSomeDiskProvider *からvoid *にキャストし直すことDisk *です。

キャスト元の正確なタイプにキャストバックする必要があります。したがって、最初にあなたSomeDiskProvider *をにキャストできますDisk *

reinterpret_cast<void*>(static_cast<Disk *>(this))

または、にキャストバックしますSomeDiskProvider *

SomeDiskProvider *pDisk = reinterpret_cast<SomeDiskProvider*>(p);
于 2010-04-21T05:35:31.347 に答える