0

次の定型文クラスの断片を考慮してください。

class ObjectA : public BaseObject
{
    DerivedMemberA a, a2, a3;
    DerivedMemberB b;
    DerivedMemberC c;
    // ...
};  

DerivedMember*タイプは共通のクラスから派生し、(BaseMemberおよびObjectA同様ObjectBの、ObjectC...)はから派生しBaseObjectます。

BaseObjectここで、パブリックインターフェイスにあり、派生クラスのメンバーへの参照を反復処理するイテレータを実装したいと思います(as BaseMember&)。

言い換えれば、使用法は次のようになります。

BaseObject& b = someObject;
for (BaseObject::iterator it = b.begin(); it != b.end(); ++it)
{
    BaseMember& m = *it;
    // ...
}

呼び出されたのObjectAは、繰り返しますaa2..。

これを解決するための最良の方法は何ですか?できれば、イテレータのサブクラス化も避けてください。そこで再利用できる準備ができているイテレータクラスまたはテンプレートはありますか?

私は、変数の数値「インデックス」を取りswitch、適切な参照を返すためにaを使用する仮想メンバー関数を実装することを考えていました。次に、インデックス保持イテレータからそのメンバーを呼び出します。

4

3 に答える 3

0

配列を使用してこれを行うのが最善です。あなたが現在持っているコード:

DerivedMemberA a, a2, a3;
DerivedMemberB b, b2;
DerivedMemberC c, c2;

実際の構造はほとんどありません。3つのDerivedMemberAオブジェクトを使用する代わりに、DerivedMemberAオブジェクトの配列を使用してみませんか?BとCについても同じことが言えます。

-レーガン

于 2012-07-09T18:13:14.480 に答える
0

迅速で汚い概念実証:

template <class Source, class Type>
class MyIterator : public std::iterator<std::input_iterator_tag, Type>
{
    typedef Type* (Source::*getter_method)(int n);

    Source& _inst;
    getter_method _getter;
    int _index;
    bool _end;
    Type* _curr_val;

public:
    MyIterator(Source& instance, getter_method method, bool end = false)
        : _inst(instance), _getter(method), _index(0), _end(end)
    {
        if (!end)
            ++*this;
    }

    void operator++()
    {
        assert(!_end);
        _curr_val = (_inst.*_getter)(_index++);

        if (!_curr_val)
            _end = true;
    }

    bool operator!=(MyIterator rhs)
    {
        return _end != rhs._end;
    }

    Type& operator*()
    {
        assert(!_end);

        return *_curr_val;
    }
};

次のように実装されたオブジェクトを使用します。

class BaseObject
{
protected:
    virtual BaseMember* iterator_getter(int n) = 0;

public:
    typedef MyIterator<BaseObject, BaseMember> iterator;

    iterator begin()
    {
        return iterator(*this, &BaseObject::iterator_getter);
    }

    iterator end()
    {
        return iterator(*this, &BaseObject::iterator_getter, true);
    }
};

および次のような派生オブジェクト:

class ObjectA : public BaseObject
{
    // ...
protected:
    virtual BaseMember* iterator_getter(int n)
    {
        BaseMember* ret;

        switch (n)
        {
            case 0:
                ret = &a;
                break;
            case 1:
                ret = &a2;
                break;
            case 2:
                ret = &a3;
                break;
            // ...
            default:
                ret = 0;
        }

        return ret;
    }

どう思いますか?

于 2012-07-09T18:16:03.207 に答える
0

C ++にはイントロスペクションの概念がないため、基本クラスが派生クラスで定義されているメンバーを知る方法はまったくありません。

最善の方法は、派生クラスごとに、独自のメンバーを反復処理する仮想関数を作成することです。

于 2012-07-09T18:16:38.270 に答える