我有一个基类,它包含指向派生类的指针向量,还有一个类似于以下的虚拟递归方法:
class Base
{
std::vector<Base*> vec;
public:
Base(std::vector<Base*> vec = {}) : vec {vec} {}
virtual ~Base() = default;
virtual void f() const
{
if (vec.size() == 0)
throw std::logic_error("Last children should implement f()")
for (auto * part : vec)
part->f();
}
}
方法f()
是递归的,Base
的最后一个子代应该覆盖它其中第一个派生类是
class B : public Base
{
B() : Base() {}
virtual void f() const
{
std::cout << "In Bn";
}
}
class A : public Base
{
B b_,c_;
public:
A(B b, B c) : Base({&b_,&c_}), b_ {b}, c_{c} {}
}
如果我打电话给
B b,c;
A a(b,c);
a.f()
它将正确打印两次"In B"
。请注意,A
不会覆盖f()
,因此会调用Base::f()
,这会循环并调用B::f()
两次,一次用于b
,一次为c
。然而,如果我多使用一个嵌套类,例如使用
class C : public Base
{
A a_;
B b_;
public:
C(A a, B b): Base({&a_, &b_}), a_{a}, b_{b} {}
}
我把C::f()
称为segfault程序。我想这是因为有一些临时性的,它们的析构函数删除了Base
所持有的指针。解决这个问题的办法是持有shared_ptr
吗?还是有更好的设计?我不能持有unique_ptr
,因为这会使所有派生类都不可复制。
public C(A a, B b): Base({&a, &b}), a{a}, b{b} {}
首先,不能有public
。
您的基点指向构造函数的参数。当构造函数完成并且指针变为无效时,这些参数将被销毁。指向成员:
C(A a, B b): Base({&this->a, &this->b}), a{a}, b{b} {}
请注意,类的隐式复制和移动构造函数以及赋值运算符已断开,因为它们将使复制的对象指向复制源的成员,而不是复制本身的成员。因此,您也需要实现这些功能。
有更好的设计吗?
可能是一种更好的方法:与其将指针存储在基子对象中,不如编写一个派生类可以覆盖的虚拟函数,该函数将一系列指针返回给子对象。