0

他のクラスが継承する基本クラス (ThinkFunc) があります。Func() は仮想 void メソッドです。

クラスの型を判別できるようにしたいので、 Func() が指しているメソッドをすばやく簡単に確認できると思いました。だから私は関数ポインタを比較しようとしています。しかし、どうやら以下のコードは許可されていません。サブクラス化された仮想関数を使用して C++ でこれを行う方法はありますか?

bool found = false;

ThinkFunc *tfNode;
for (tfNode = this->thinkfuncs; tfNode; tfNode = (ThinkFunc*)tfNode->next)
{
    if (tfNode->Func == &Thinkers::GroupBoxBouncePan::Func)
    {
        found = true;
        break;
    }
}
4

3 に答える 3

1

C++ 言語では、関連するポインターの少なくとも 1 つが仮想メソッドを指している場合、メソッド ポインターの比較の結果は規定されていません。つまり、このアプローチを使用してオブジェクトの動的タイプを判別することはできません。

その理由は、C++ ではメソッド ポインターが「多態的」であるためです。初期化の時点では初期ではなく、呼び出しの時点で遅く、仮想メソッドの特定のバージョンにバインドされます。. この動作を実装するために、仮想メソッドのアドレスで初期化されたメソッド ポインターの物理値は、実際には中間の「ディスパッチャー」コードへのエントリ ポイントになります。(これは可能な実装の 1 つです。代替の実装が存在します。) その中間コードは、呼び出しで使用されるオブジェクトの動的な型に応じて、適切な仮想ディスパッチを実行することになっています。中間コードは、まったく関係のない仮想関数で共有できます。その実際的な結果は、まったく関係のない仮想関数を指すメソッド ポインターが同等である可能性があることです。言語仕様では、そのような比較の結果は指定されていないとだけ述べています。

ポリモーフィック オブジェクトの動的な型を決定できる言語機能はtypeid、 およびdynamic_castです。

于 2013-09-11T17:36:15.697 に答える
1

通常、仮想メソッドのアドレスを取得すると、実際のメソッドのアドレスではなく、トランポリンまたは「サンク」のアドレスが取得されます。次のように使用しない理由dynamic_cast:

bool found = false;

ThinkFunc *tfNode;
for (tfNode = this->thinkfuncs; tfNode; tfNode = (ThinkFunc*)tfNode->next)
{
    if (dynamic_cast<Thinkers::GroupBoxBouncePan*>(tfNode) != null)
    {
        found = true;
        break;
    }
}

それをしたくない場合はIsA、WhozCraig が提案するような何らかの機能を実装することをお勧めします。

于 2013-09-11T17:23:56.610 に答える
0

const static std::string TYPE各サブクラスのメンバー (たとえば、サブクラスの名前を保持する文字列) と、virtual std::string getType()その TYPE メンバーを返すメソッドを持つことができます。そうすれば、ポインターによって返された値を比較できます。

ThinkFunc.h

class ThinkFunc{
    public:
    virtual const std::string& getType();
};

GroupBoxBouncePan.h

namespace Thinkers{
    class GroupBoxBouncePan{
        public:
        static const std::string TYPE;
        virtual const std::string& getType(); // returns TYPE
    };
};

GroupBoxBouncePan.cpp

const std::string Thinkers::GroupBoxBouncePan::TYPE = "Thinkers::GroupBoxBouncePan";
const std::string& Thinkers::GroupBoxBouncePan::getType(){
    return TYPE;
}

そして、検索は次のようになります。

bool found = false;

ThinkFunc *tfNode;
for (tfNode = this->thinkfuncs; tfNode; tfNode = (ThinkFunc*)tfNode->next)
{
    if (tfNode->getType() == Thinkers::GroupBoxBouncePan::TYPE)
    {
        found = true;
        break;
    }
}
于 2013-09-11T18:11:43.587 に答える