Конверсионный конструктор с передачей ответственности - PullRequest
0 голосов
/ 14 октября 2011

Это продолжение этого вопроса.

Мне нужно реализовать операцию преобразования, чтобы передать ответственность за объект-член от одного объекта к другому.Операция преобразования происходит в иерархии классов.Существует класс Base и два производных класса, скажем Child1 и Child2.В классе Base есть динамически созданный объект, который мне нужно передать от Child1 до Child2 (вместе с ответственностью), пока происходит преобразование, и не позволяет деструктору Child1 уничтожить его.Я написал простой пример, чтобы проиллюстрировать, чего я пытаюсь достичь:

#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;
}

И результат такой:

In Base constructor, reserving memory.
Child1: 158711832:3 2
In Base copy-constructor.
Child2: 158711832:3 2
Freeing memory.
Child2: 158711832:0 2
Freeing memory.

Есть ли способ сделать то, что япытаясь сделать чистым способом?Я не могу скопировать конструкцию p_int, потому что она очень тяжелая.Проект представляет собой встроенный AVR-проект, поэтому смарт-указатели или библиотека повышения могут быть недоступны (хотя я не знаю) - я просто припоминаю, что это может быть решением, но я их еще никогда не использовал.

1 Ответ

2 голосов
/ 14 октября 2011

Я думаю, вам нужно посмотреть на подсчитанные ссылками объекты. По сути, сам объект отслеживает свое использование сам, и вместо хранения необработанного указателя на объект, вы используете указатель с подсчетом ссылок.

Скотт Мейерс говорит об этом здесь:

http://www.aristeia.com/BookErrata/M29Source.html

Поскольку вы работаете во встроенной системе, я не уверен, что вы можете использовать boost::shared_ptr<>, но ничто не мешает вам реализовать это, как наметил Мейерс.

Таким образом, вместо того, чтобы иметь необработанный указатель на рассматриваемый объект в базовом классе, используйте общий указатель / указатель с подсчетом ссылок, который предотвратит удаление объекта, как только он будет скопирован в Child2. По конструкции Child2 у него будет 2 ссылки, поэтому он не умрет, когда будет удален Child1. Однако это произойдет, когда Child2 будет удален.

...