【问题标题】:Need help on the Dynamic Binding During Initialization idiom需要有关初始化期间动态绑定习语的帮助
【发布时间】:2015-05-01 08:39:20
【问题描述】:

我有以下代码:

class A {
  public:
    A();
    virtual int Compute() = 0;

    int inited_val;
};

class B: A {
  public:
    B(int data): mydata(data) {};
    int Compute();
    int mydata;
};

A::A() {
  inited_val = Compute();
};

int B::Compute() {
  return mydata; // long computation...
}

int main() {
  B b(42);
  return 0;
}

这将不起作用,因为不可能在基类的构造函数中使用B::Compute(它会调用不存在的A::Compute)。

如何确保inited_val 是从派生类中的Compute 函数中填充的?我可以从 B 构造一个对象并在之后填充它,或者使用在构造函数之后直接调用的 init 函数,但这似乎容易出错(我可能会忘记这样做)。 (想象一下Compute 函数的成本很高,并且使用的数据仅在派生类中可用。)

我在http://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctor-idiom 上找到了如何解决此问题的建议,并尝试使用create 函数来实现该方法,但我不清楚如何在不明确依赖B 的情况下编写A::create

A* A::Create() {
  A* p = ???;
  inited_val = p->Compute();
  return p;
}

【问题讨论】:

  • 不能把继承改成public,从派生类构造函数初始化inited_val吗?
  • 这是可能的,但是从 A 派生的每个人都需要这样做并且不要忘记这一点。 (而且它也会重复代码,因为该行在所有派生构造函数中都是相同的。)

标签: c++ inheritance constructor initialization


【解决方案1】:

你可以像这样实现Create

template <class T>
static std::unique_ptr<typename std::enable_if<std::is_base_of<A, T>::value, T>::type> Create()
{
    auto t = std::make_unique<T>();
    inited_val = t->Compute();
    return t;
}

你可以这样使用它

auto b = Create<B>();

【讨论】:

    【解决方案2】:

    考虑使用CRTP

    template<class T> class Wrapper : public T
    {
    public:
      template<class... Types>
      Wrapper(Types&&... Args)
        : T(std::forward<Types>(Args)...)
      {
        inited_val = Compute();
      }
    };  
    
    
    int main() 
    {
      Wrapper<B> b(42);
      return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多