C++对派生实例的成员进行迭代的正确设计

  • 本文关键字:迭代 派生 实例 成员 C++ c++
  • 更新时间 :
  • 英文 :


我有一个基类,它包含指向派生类的指针向量,还有一个类似于以下的虚拟递归方法:

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} {}

请注意,类的隐式复制和移动构造函数以及赋值运算符已断开,因为它们将使复制的对象指向复制源的成员,而不是复制本身的成员。因此,您也需要实现这些功能。

有更好的设计吗?

可能是一种更好的方法:与其将指针存储在基子对象中,不如编写一个派生类可以覆盖的虚拟函数,该函数将一系列指针返回给子对象。

最新更新