std::vector 个 Derived class 个实例,其 Bases 包含(原始)指针

std::vector of Derived class instances whose Bases contain a (raw) pointer

假设我有以下结构

class BaseKernel {
   // .......
}

class DerivedKernel : public BaseKernel {
   // .......
}

class A {
  public:
    A(BaseKernel* kernel) : kernel(kernel) {}
    A(const A& a) : kernel(a.kernel) {}
   ~A() {delete kernel;}

    BaseKernel* kernel;
}

class B : public A {
  public:
    B(BaseKernel* kernel) : A(kernel) {}
    B(const B& b) : A(b) {}
   ~B() = default;
}

class C : public B {
  public:
    C() = default;
    C(BaseKernel* kernel) : B(kernel) {}
    C(const C& c) : B(c) {}
   ~C() = default;
}

class D {
  public:
    D() = default;
    D(std::vector<C> collection) : collection(collection) {}

    std::vector<C> collection;
}

class E {
  public:
    E(std::vector<D> dollection) : dollection(dollection) {} // lmfao, dollection for the lack of a better word
    
    std::vector<D> dollection;
}

有以下用法

BaseKernel* kernel1 = new DerivedKernel(...);
BaseKernel* kernel2 = new DerivedKernel(...);

C c_obj1(kernel1);
C c_obj2(kernel2);

std::vector<C> collection1(1, c_obj1);
std::vector<C> collection2(1, c_obj2);

std::vector<D> dollections = {collection1, collection2};
// At this point kernel1 and kernel2 are deleted.
E e_obj(dollections) // Useless now

由于我是 C++ 的新手,因此不熟悉智能指针(但我相信解决方案是使用后者),我将如何使用原始指针处理这种情况? (更好的是,使用适当的智能指针的解决方案会很棒)

c_obj1c_obj2 的初始化很好(kernel1kernel2 仍然存在),但特别是 dollections 我需要初始化带括号的向量(因为我会有不同的 collections),调试后它首先通过复制构造函数,然后最终通过析构函数 ~A()?

我发现了一些问题。我会看看我是否能理解你真正的问题。让我们从这个开始:

class A {
  public:
    A(BaseKernel* kernel) : kernel(kernel) {}
    A(const A& a) : kernel(a.kernel) {}
   ~A() {delete kernel;}

    BaseKernel* kernel;
}

这很糟糕。如果您使用复制构造函数,您将最终删除相同的数据两次。想象一下:

 BaseKernel * k = new BaseKernel();
 A first(k);
 A second(first);

这个this点,first.kernel和second.kernel都指向k。现在,当它们超出范围时,两个析构函数都会尝试删除它们的内核指针,因此 k 将被删除两次。

我不太明白你问的问题。但是,我不鼓励使用原始指针并鼓励使用智能指针。 std::unique_ptr 效率更高,但我倾向于总是使用 std::shared_ptr 如下:

class A {
  public:
    A(std:: shared_ptr <BaseKernel> kernelIn) : kernel(kernelIn) {}
    A(const A& a) : kernel(a.kernel) {}
   ~A() { /* Nothing needed */ }

    std:: shared_ptr <BaseKernel> kernel;
};

然后……

std::shared_ptr<BaseKernel> kernel1 = std::make_shared<DerivedKernel>(...);

不过,您可能需要做一个 dynamic_pointer_cast。我通常不喜欢使用我指向的数据类型,所以通常不会在这里使用,而是:

std::shared_ptr< DerivedKernel> kernel1 = std::make_shared<DerivedKernel>(...);

然后 dynamic_pointer_cast 稍后根据需要进行。

我不确定这是否能让你更进一步。