5

重複の可能性:
類似したconstおよびnon-constメンバー関数間のコード重複を削除するにはどうすればよいですか?

私には2人のメンバーがいます

A &B::GetA (int i)
{
    return *(m_C[m_AtoC[i]]);
}

const A &B::GetA (int i) const
{
    return *(m_C[m_AtoC[i]]);
}

今のところ私はコードを複製するだけですが、それを行うための良い方法が存在するかもしれません。私は確かにconstからnon-constへの型キャストを扱いたくありません。

編集:コードの重複を避けるために、あるメンバーを別のメンバーに呼び出したいと思います。

4

6 に答える 6

2

[修正に注意してください。最初は間違った方向に進んで申し訳ありません。]

これは、を使用するのに適した状況でconst_castあり、non-const関数から対応するconst関数に呼び出しを転送することにより、コードを重複排除できます。

A & B::GetA(int index) 
{
    return const_cast<A &>(static_cast<B const *>(this)->GetA(index));
}

これは一方向でのみ実行する必要があることに注意することが重要ですnon-const。定数の観点からメソッドを実装できますが、その逆はできません。定数を呼び出すとGetA()、問題のオブジェクトへの定数参照が取得されます。オブジェクトを変更しても実際には問題ないという追加情報があれば、結果から定数を安全にキャストできます。

ScottMeyerのEffectiveC++には、まさにこの手法に関する章もあります。

于 2013-01-18T14:33:24.930 に答える
1

あなたは次のようなことをすることができます:

class B {
public:
    A& GetA (int index) { return GetA_impl(index); }
    const A& GetA (int index) const { return GetA_impl(index); }
private:
    A& GetA_impl (int index) const { return *(m_C[m_AtoC[i]]); }
};

この場合、本当に努力する価値があるかどうかはわかりませんが、重複する可能性のあるコードがより複雑になる場合は、これが役立つ可能性があります。

于 2013-01-18T14:36:38.100 に答える
1

少しのテンプレートメタプログラミングでconst_castを回避できます。

// This meta function returns a const U if T is const, otherwise returns just U.
template <typename T, typename U>
make_same_const<T, U>
{
    typedef typename std::conditional<
            std::is_const<T>::value,
            typename std::add_const<U>::type,
            U
        >::type type;
};


// Generic version of a function. Constness of return type depends on
// constness of T.
// This is a static member template of B.
template <typename T>
make_same_const<T, A>::type& B::GetA(T& obj, int i)
{
    return *(obj.m_C[obj.m_AtoC[i]]);
}

A&       B::GetA(int i)       { return B::GetA(*this, i); }
A const& B::GetA(int i) const { return B::GetA(*this, i); }
于 2013-01-18T15:05:34.510 に答える
0

どうですか

const A &B::GetA (int index) const
{
    return *(const_cast<B*>(this)->GetA(index));
}
于 2013-01-18T14:31:05.060 に答える
0

IMOこれは、重複排除する価値のある十分なコード(または複雑さ)ではありません。

const_cast両方のベースのソリューションでわかるように、キャスト式は実際には元のコードよりも長くなっています。

でも、もっと長くて複雑な表現が気になる方は見せてください。

于 2013-01-18T14:37:18.883 に答える
0

との本体が同一であると仮定すると(つまりGetA()、変更されない)、非constバージョンを使用してconstバージョンを実装するために1つを安全に使用できます。GetA() constGetA()*thisconst_cast

const A& B::GetA() const {
  return const_cast<B*>(this)->GetA();
}

non-constGetA()はオブジェクトを変更しないため、オブジェクトで呼び出すことconst Bは未定義ではありません。non-constによって返されるnon-const参照は、から返される前にGetA()aに変換されるため、そこでも未定義の動作の危険はありません。const&GetA() const

于 2013-01-18T14:48:35.417 に答える