Conversion constructor with responsibility transfer
This is a follow up of this question.
I need to implement a conversion operation to pass responsibility for a member object from one object to another. The conversion operation takes place in a class hierarchy. There is a Base
class and two deriving classes, say Child1
and Child2
. In the Base
class, there is a dynamically created object I need to pass from Child1
to Child2
(along with responsibility) while the conversion happens and not let Child1
's destructor destroy it. I've written a simple example to illustrate what I'm trying to achieve:
#include <iostream>
using namespace std;
class Base {
public:
Base() {
p_int = new int; *p_int = 0;
cout << "In Base constructor, reserving memory." << endl;
}
Base(const Base& other) : p_int(other.p_int), a(other.a) {
cout << "In Base copy-constructor." << endl;
}
virtual ~Base() { delete p_int; p_int = NULL; cout << "Freeing memory." << endl; }
void setpInt(int val) { *p_int = val; }
void setInt(int val) { a = val; }
virtual void print() {
cout << "Base: ";
cout << (long)p_int << ":" << *p_int << " " << a << endl;
}
protected:
int* p_int;
int a;
};
class Child1 : public Base {
public:
Child1() : Base() {};
Child1(const Base& base) : Base(base) {}
void print() {
cout << "Child1: ";
cout << (long)p_int << ":" << *p_int << " " << a << endl;
}
};
class Child2 : public Base {
public:
Child2() : Base() {};
Child2(const Base& base) : Base(base) {}
void print() {
cout << "Child2: ";
cout << (long)p_int << ":" << *p_int << " " << a << endl;
}
};
int main() {
Child1* c1 = new Child1();
c1->setpInt(3);
c1->setInt(2);
c1->print();
Child2* c2 = new Child2(*c1);
c2->print();
delete c1; //Obviously c1's destructor is called here.
c2->print();
delete c2;
return 0;
}
And the outcome is:
In Base constructor, reserving memory.
Child1: 158711832:3 2
In Base copy-construct开发者_开发百科or.
Child2: 158711832:3 2
Freeing memory.
Child2: 158711832:0 2
Freeing memory.
Is there a way to do what I'm trying to do in a clean way? I can't copy-construct p_int
because it's very heavy. The project is an embedded, AVR-project, so smart-pointers or boost library might not be available (I don't know, though) - I just recall this might be a solution, but I've never used them yet.
I think you need to look at reference-counted objects. Essentially, the object itself tracks it's usage itself, and instead of storing a raw pointer to the object, you use a reference-counted pointer.
Scott Meyers talks about this here:
http://www.aristeia.com/BookErrata/M29Source.html
As you're on an embedded system, I'm not sure you can use boost::shared_ptr<>
but there's nothing stopping you implementing this as Meyers outlines.
So, instead of having a raw pointer to the object in question in the base class, have a shared pointer/reference-counted pointer that will prevent the deletion of the object once it gets copied in to Child2
. By the construction of Child2, it will have 2 references so won't die when Child1 gets deleted. It will, however, when Child2 is deleted.
精彩评论