1

免責事項私はBOOSTまたは他のライブラリを使用することは許可されていません。標準のみです。

私のクラスには、オブジェクトへのポインターとこのオブジェクトへのポインター-メンバー関数の2つのパラメーターをFoo受け取るテンプレート関数があります。ご覧のとおり、この関数は任意のクラスのポインターで機能します。どのクラスが渡されるのかわかりません。この関数は、テンプレート構造のインスタンスを作成します。foofoo

template <typename TypeName>
struct Bar
{
    void(TypeName::*action)();
    TypeName* objPtr;
};



template <typename TypeName> void Foo::foo ( void(TypeName::*action)() , TypeName* objPtr )
{
    Bar <TypeName> bar;
    bar.action = action;
    bar.objPtr = objPtr;
};

私の質問はBar、で作成されたのオブジェクトをどのように格納するかですfoo。これにより、後でそれらを反復処理して、次のようにオブジェクトメンバー関数へのポインタを呼び出すことができます。

(BarStorage[i].objPtr->*BarStorage[i].action)();
4

1 に答える 1

5

型消去を使用する:

class BarBase {
    virtual void invoke() = 0;
};

template<typename TypeName>
class Bar final : public BarBase {
    void(TypeName::*action)();
    TypeName* objPtr;
    virtual void invoke() override { (objPtr->*action)(); }
};

class Foo {
    std::vector<std::unique_ptr<BarBase>> myBars;
/* ... */
};

template <typename TypeName>
void Foo::foo ( void(TypeName::*action)() , TypeName* objPtr)
{
    auto bar = new Bar<TypeName>();
    bar->action = action;
    bar->objPtr = objPtr;
    myBars.emplace_back(bar);
};

次に、単に電話しますmyBars[x]->invoke();


コメントで質問に答えるため。

どうしたのoverride基本クラスから仮想関数をオーバーライドすると明示的に言います。これはここでは実際には必要ありませんが、良い習慣と考えられています。詳細については、ウィキペディアの記事を参照してください。

C ++ 11の新機能であり、一部のコンパイラはこの機能を長い間何らかの形でサポートしていましたが、現在は標準化されています。GCCはバージョン4.7からこの機能をサポートする必要があります-コマンドラインパラメータを使用する必要があります-std=c++0x

どうしたのunique_ptrそれは人生を楽にします。を割り当てるときnew Bar<XXX>()は、ある時点でdeleteそのメモリを解放するように指示する必要があります。のようなリソース管理オブジェクトにポインタを置くと、unique_ptrそれを削除することを心配する必要がなくなります。すると、次のようなことをvector<BarBase*>行うデストラクタを宣言する必要があります。Foo

for each element in myBars
    delete element

を使用する場合はvector<unique_ptr<BarBase>>、何も削除する必要はありません。が寿命のvector終わりに破壊されると、その要素が破壊され、自身のデストラクタに含まれているメモリが削除されます。Foounique_ptr

これはC++11の機能でもあります-標準ライブラリへの追加です。使用する必要はありません(ただし、最後にすべてを削除してください)。

どうしたのauto同じ型を2回繰り返す代わりに(Bar<Type> * bar = new Bar<Type>();)、1回使用するだけで、コンパイラーに初期化子の型に基づいて変数の正しい型を推測させます。動作はまったく同じで、タイピングが少なく、見栄えも良くなります:)

また、C ++ 11機能、v4.4以降のGCCでサポートされています。

なぜmyBars[x]->invoke()正しいことですか?invokeで仮想として宣言されているためBarBase。これは、実行されるメソッドが、静的タイプではなく、の動的タイプ(実行中の実際のタイプ)に基づいて選択されることを意味しmyBars[x]ます。詳細な説明については、Wikiを参照してください。このメカニズムには実行時のオーバーヘッドがわずかにありますが、動的型を処理する場合は役に立ちません。

于 2012-08-28T11:31:14.830 に答える