Say I had the following structure
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;
}
With the following usage
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
As im relatively new to C++ and therefore unfamiliar with smart pointers (i believe the solution is with the latter, however), how would I handle such a case with raw pointers? (Better yet, a solution using the appropriate smart pointer would be great)
The initialization of c_obj1
and c_obj2
were fine (kernel1
and kernel2
still lives), but specifically for dollections
I would need to initialize the vector with brackets (as I would have different collections
) and after debugging it first goes through the copy constructors then ultimately the destructor ~A()
?
I see some problems. I'll see if I can understand your real question. Let's start with this:
class A {
public:
A(BaseKernel* kernel) : kernel(kernel) {}
A(const A& a) : kernel(a.kernel) {}
~A() {delete kernel;}
BaseKernel* kernel;
}
This is bad. If you use your copy constructor, you'll end up deleting the same data twice. Imagine this:
BaseKernel * k = new BaseKernel();
A first(k);
A second(first);
This this point, both first.kernel and second.kernel point to k. Now, when they go out of scope, both destructors will attempt to delete their kernel pointer, so k will get deleted twice.
I don't quite understand the question you're asking. However, I discourage the use of raw pointers and encourage smart pointers. std::unique_ptr
is more efficient, but I tend to always use std::shared_ptr
as follows:
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;
};
Then later...
std::shared_ptr<BaseKernel> kernel1 = std::make_shared<DerivedKernel>(...);
You'll probably need to do a dynamic_pointer_cast
, though. I usually don't like using the datatype I'm pointing to so would normally not do it here but instead:
std::shared_ptr< DerivedKernel> kernel1 = std::make_shared<DerivedKernel>(...);
And then dynamic_pointer_cast it as necessary later.
I'm not sure if this gets you further.