0

Basetype のデフォルト パラメータ値を持つクラスの静的メソッドが必要ですDerived。オーバーロードを使用せずにこれを実装する方法はありますか? (ここを参照)。

class Base;
class Derived;
Derived make_derived(void);

class Base
{
  public:
    static void problem_here(Base && = make_derived());
};

class Derived : public Base
{
};

Derived make_derived()
{
  return Derived();
}

... incomplete type の使用に関するエラーが表示されますDerived。ただし、基本クラスの定義の後に定義する必要があるため、の定義をDerived前に配置することはできません。problem_hereBase

残念ながら、からポインターを返すことmake_derivedはできません。

problem_here今まで思いついたのはオーバーロードだけですが、「実際の」problem_hereメソッドは2つ(および別の3つ)のパラメーターを取り、それはライブラリの一部であるため、これにより...

static void problem_here(Thing const &, Base const &);
static void problem_here(Thing const &, Base &&);
static void problem_here(Thing const &); // Default param "hack"
static void problem_here(Thing &&, Base const &);
static void problem_here(Thing &&, Base &&);
static void problem_here(Thing &&); // Default param "hack"

.. 2 つのパラメーターの場合のみ。

同じパフォーマンス (パラメーター コンスタレーションの不要なコピー/移動構築がない) と呼び出し元サイトでの同じ動作を維持しながら、これらすべての関数シグネチャを記述することを回避する方法はありますか?


problem_hereのような複数の関数があり、すべての保護されたコンストラクターDerived(およびその多くの兄弟のコンストラクター) にアクセスする必要があることを追加する必要があります。したがって、これらのメソッドを Base の静的メンバーにする主な理由はfriend class Base;、すべての関数をフレンドシップするのではなく、各派生クラスでできるようにするためです。


リファクタリングにより、派生クラスの保護されたコンストラクターにアクセスするコードを単一のファクトリー関数に移動できることがわかりました。そうすれば、デフォルトのパラメーターを使用して関数を外部に移動しBase、ファクトリーを呼び出すことができます。今でも、これらの関数のすべてをフレンドリにする必要がありますが、(Baseファクトリへのアクセスを許可するために) 1 回だけです。すべての関数をヘルパー クラスに配置し、代わりにそれをフレンドにすることでこれを回避できますが、それは私にはハックのように見えます。

class Base
{
  friend class Helper; // The Hack
  friend void no_problem_here(Base &&); // No hack, more writting


  protected:
    static void factory(Thing && from_which_I_can_construct_the_correct_derived_class);
    // return type void to keep it simple, move parameter type because special cases
    // handled in "trampoline" functions and a copy of the Thing must be stored either
    // way.
};
class Derived : public Base
{
  friend class Base;
  // protected constructor omited for simplicity.
}


void no_problem_here(Base && = make_derived());
// ...
void no_problem_here(Base && b)
{
   // work, and then call Base::factory
}

// or

class Helper
{
  protected:
    // Constructors ...
  public:
    static void no_problem_either(Base && = make_derived());
};
4

1 に答える 1

4

宣言は複数回行うことができるため、次の回避策が役立つ場合があります。

class Base;
class Derived;
Derived make_derived(void);

class Base
{
public:
    static void problem_here(Base &&);
};

class Derived : public Base {};

void Base::problem_here(Base && = make_derived()) { /* ... */ }

そのようなコードの因数分解に問題がある場合は、いつでも小さなトランポリン関数を挿入できます。

 class Base
 {
 public:
     static void problem_here(Base &&);
 private:
     static void problem_here_impl(Base &&);
 };

 inline void Base::problem_here(Base && x = make_derived())
 { problem_here_impl(std::move(x)); }
于 2014-03-07T09:47:42.670 に答える