使用派生类实例作为默认参数值

时间:2014-03-07 09:38:16

标签: c++ inheritance c++11 forward-declaration default-parameters

我需要一个Base类的静态方法,其默认参数值类型为Derived。 有没有办法在不使用重载的情况下实现它? (见here)。

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();
}

...给我一个关于不完整类型Derived的使用的错误。但是,我不能将Derived的定义放在problem_here之前,因为它必须在其基类Base的定义之后定义。

不幸的是,从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"

..仅适用于两个参数案例。

有没有办法避免编写所有这些功能签名,同时仍然保持相同的性能(没有任何参数星座的不必要的复制/移动构造)和调用者站点上的相同行为?


我应该补充说,有多个函数,如problem_here,并且都需要访问Derived的受保护构造函数(以及它的许多兄弟姐妹的构造函数)。因此,使这些方法成为Base的静态成员的主要原因是能够在每个派生类中friend class Base;而不是为每个函数提供友好。


重构告诉我,我可以将访问派生类的受保护构造函数的代码移动到单个工厂函数中。这样,我就可以使用Base之外的默认参数移动函数,并让调用工厂。现在我仍然需要与这些函数中的每一个相关,但只需要一次(在Base中授予他们访问工厂的权限)。我可以通过将所有函数放入一个帮助程序类并对其进行友好来避免这种情况,但这看起来像是对我的攻击。<​​/ p>

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());
};

1 个答案:

答案 0 :(得分: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)); }