-1

私はこのような構造体を持っています:

struct foo
{
    IBar* ptr;
};

これは、有効期間が長い foo オブジェクトの一部です。ユーザーは、さまざまなコールバックでこれらのオブジェクトのインスタンスを取得することが多く、特定の場所で IBar* に何かを挿入し、後のコールバックで使用して、最終的に解放します。(IBar にはvirtual void free() { delete this; }もちろんオーバーライド可能なものがあります)。

問題は、foo 構造体ごとに複数のユーザーを持つ可能性にユーザーを移行しIBar*、移行をスムーズにしたいことです。移行をスムーズにするための 1 つのアイデアは、次のように foo 構造体を変更することです。

struct foo
{
    foo()
    {
        ptr = reinterpret_cast<IBar*>(new IBar*[N]);
        memset(ptr, 0, sizeof(IBar*)*N);
    }

    IBar*& getBarPtr(size_t offset)
    {
        return reinterpret_cast<IBar**>(ptr)[offset];
    }

    IBar* ptr;
};

私の考えでは、このように、1 つしかないと予想される古いスタイルを使用している人は、通常の使用方法で透過的にIBar*最初のものを使用することにフォールバックする必要があります。N

someFoo.ptr = new iImplementIBar(...);

しかし、新しい使用法に移行し始めたユーザーは、オフセットを取得して代わりに使用することができます

someFoo.getBarPtr(myOffset) = new iImplementIBar(...);

ただし、問題は、これを行うために使用されるメソッドがfooあったことです。reset

void reset() {
    if (ptr)
    {
        ptr->free();
        ptr = 0;
    }
}

このアイデアはこれに置き換えられます:

void reset() {
    IBar** ptrs = reinterpret_cast<IBar*>(ptr);
    for (size_t i = 0; i < N; ++i)
         if (ptrs[i])
        {
            ptrs[i]->free();
            ptrs[i] = 0;
        }
}

上記の の機能はfree失われているようです。これを機能させる方法はありますか?または何がうまくいかないのですか?

4

2 に答える 2

0

新しいインターフェイスを実装せずにこれを行う必要がある場合は、次のようなものを用意してください。

struct foo
{
    IBar **bars; // or better yet: std::array or std::vector if size of N is fixed.
    IBar *ptr;

    IBar *getBar(int index)
    {
        ...
    }

    ...
};

そうすれば、既存の 'foo' インターフェイスのユーザーは引き続き使用できますptrが、新しいbarsインターフェイスを使用したい人も利用できます。

詳しく知らなければ、上記の設計が理にかなっているのかどうかを判断するのは困難です。

于 2012-12-04T00:48:57.943 に答える
0

この複雑で手動のライフタイム管理設計を使用することを推奨しなくても、セット全体を解放しながらセット内の最初の IBar に転送するダミーの IBar を作成することができます。

#include <iostream>
#include <new>

// existing:
struct IBar
{
    virtual void method() =0;
    virtual void free() =0;
};

struct Bar : public IBar
{
    virtual void method() { }
    virtual void free() { delete this; }
};

struct foo
{
    virtual void reset() { if (ptr) {ptr->free();}}
    IBar* ptr;
};

// proposed:
struct fooset;

struct foosetwrap : public IBar
{
    virtual void method();
    virtual void free();
    fooset* ptrOwner;
};

struct fooset : public foo
{
    fooset(IBar** begin, IBar** end) : ptrBegin(begin) , ptrEnd(end) 
        { wrapper.ptrOwner = this; ptr = &wrapper; }
    IBar** begin(){return ptrBegin;}
    IBar** end(){return ptrEnd;}
    virtual void reset() {for(auto& expired : *this) { if (!!expired) { expired->free(); }}}
private:
    foosetwrap wrapper;
    IBar** ptrBegin;
    IBar** ptrEnd;
};

void foosetwrap::method() { (*(ptrOwner->begin()))->method(); }
void foosetwrap::free() { ptrOwner->reset(); }

int wmain(int argc, wchar_t* argv[])
{
    IBar* bars[]={new(std::nothrow) Bar(),new(std::nothrow) Bar()};

    fooset set(std::begin(bars), std::end(bars));
    set.ptr->method();
    set.ptr->free();
    return 0;
}
于 2012-12-04T01:18:46.703 に答える