1. ホーム
  2. c++

[解決済み] [Solved] 似たようなconstとnon-constのメンバ関数間のコードの重複を取り除くには?

2022-04-19 08:39:23

質問

例えば、次のようなものがあるとします。 class X ここで、内部メンバーへのアクセスを返したい。

class Z
{
    // details
};

class X
{
    std::vector<Z> vecZ;

public:
    Z& Z(size_t index)
    {
        // massive amounts of code for validating index

        Z& ret = vecZ[index];

        // even more code for determining that the Z instance
        // at index is *exactly* the right sort of Z (a process
        // which involves calculating leap years in which
        // religious holidays fall on Tuesdays for
        // the next thousand years or so)

        return ret;
    }
    const Z& Z(size_t index) const
    {
        // identical to non-const X::Z(), except printed in
        // a lighter shade of gray since
        // we're running low on toner by this point
    }
};

2つのメンバー関数 X::Z()X::Z() const は、中括弧の中に同じコードがあります。 これは重複したコードです また、複雑なロジックを持つ長い関数では、メンテナンス上の問題を引き起こす可能性があります。 .

このコードの重複を回避する方法はありますか?

解決方法は?

はい、コードの重複を避けることは可能です。 constメンバ関数でロジックを記述し、非constメンバ関数でconstメンバ関数を呼び出し、戻り値を非const参照(関数がポインタを返す場合はポインタ)に再キャストすればいいのです。

class X
{
   std::vector<Z> vecZ;

public:
   const Z& z(size_t index) const
   {
      // same really-really-really long access 
      // and checking code as in OP
      // ...
      return vecZ[index];
   }

   Z& z(size_t index)
   {
      // One line. One ugly, ugly line - but just one line!
      return const_cast<Z&>( static_cast<const X&>(*this).z(index) );
   }

 #if 0 // A slightly less-ugly version
   Z& Z(size_t index)
   {
      // Two lines -- one cast. This is slightly less ugly but takes an extra line.
      const X& constMe = *this;
      return const_cast<Z&>( constMe.z(index) );
   }
 #endif
};

NOTE することが重要です。 NOT のロジックを非 const 関数に置き、const 関数で非 const 関数を呼び出すようにします。 なぜなら、定数クラスのインスタンスは定数でないインスタンスとしてキャストされるからです。 C++の標準では、これは未定義の動作になるとされています。