如何使用std :: function初始化抽象类中的成员,其中调用纯虚拟成员?

时间:2016-07-21 20:43:22

标签: c++ c++11 constructor

问题在于:

我有一个名为Object的类,其构造函数接受std::function这样的:

#include <functional>
#include <iostream>
#include <memory>
#include <string>

class Object {
 public:
  Object(std::function<void(int param)> f) : func(f) {}
  ~Object() { func(0); }
 private:
  std::function<void(int param)> func;
};

然后是一个抽象基类和几个派生类,如下所示:

class AbstractBase {
 public:
  AbstractBase() {
    // How to initialize object.
  }
  virtual std::string toString() const = 0;

 private:
  Object object;
};

class Derived1 : public AbstractBase {
 public:
  std::string toString() const override { return "Derived1"; }
}

class Derived2 : public AbstractBase {
 public:
  std::string toString() const override { return "Derived2"; }
}

我正在尝试初始化object中的AbstractBase,如下所示:

AbstractBase()
    : object([this](int param) {
        // do something
        std::cout << toString() << std::endl;
        // do something
      }) {}

它成功编译,但提出了纯粹的虚拟方法,称为&#34;何时删除AbstractBase。那么如何在object中初始化AbstractBase并确保在toString中调用派生类的std::function

2 个答案:

答案 0 :(得分:2)

这里的问题是析构函数调用的顺序。 这是一个简单的例子:

#include <functional>
#include <iostream>
#include <memory>
#include <string>
using namespace std;

class Object {
 public:
  Object(){ cout<<"O\n"; }
 ~Object() { cout<<"~O\n"; }
};

class AbstractBase {
 public:
  AbstractBase(){ cout<<"A\n"; }
 ~AbstractBase() { cout<<"~A\n"; }

 private:
  Object object;
};

class Derived1 : public AbstractBase {
 public:
 Derived1() : AbstractBase()
 { cout<<"1\n"; }
 ~Derived1() { cout<<"~1\n"; }
};

class Derived2 : public AbstractBase {
 public:
 Derived2() : AbstractBase()
 { cout<<"2\n"; }
 ~Derived2() { cout<<"~2\n"; }
};

int main() {
    Derived1 d1;
    Derived2 d2;

    return 0;
}

输出:

O
A
1
O
A
2
~2
~A
~O
~1
~A
~O

正如您所见,在Derived *析构函数之后调用Objects析构函数,因此,在您的代码中,Object试图调用已经被破坏的Derived *方法。

答案 1 :(得分:0)

C ++标准禁止从构造函数或析构函数中调用纯虚方法。

如果你要从toString()直接调用~AbstractBase(),你几乎肯定会遇到编译错误。

你使用lambda基本上是&#34;偷偷摸摸&#34;通过编译器的不允许的行为。

相反,您需要将责任移至Derived - 请考虑以下事项:

struct Object {
     Object(decltype(func) f) : func(f) {};
     ~Object() { func(); }
   private:
     std::function<void()> func; //removed param since it's unused in your example
};

struct AbstractBase {
    A() = delete;
  protected:
    A(Object&& o) : obj(o) {} //we'll be using an rvalue in this example, be mindful of object lifetime in other usages
  private:
    Object& o;
};

struct Derived : AbstractBase {
    Derived() : AbstractBase(Object{[this]() { writestr(); }}) {}
  private:
    void writestr() { std::cout << "yes"; }
};

int main() {
    Derived d;
    return 0;
}