问题在于:
我有一个名为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
?
答案 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;
}