|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » *Теория* | C++ | Самоубийство класса |
|
*Теория* | C++ | Самоубийство класса
|
Ветеран Сообщения: 1180 |
Профиль | Отправить PM | Цитировать Есть два класса (С++) A и B (производные от одного и того же, например), которые нужно использовать по-очереди (они отражают внутреннее состояние другого большого объекта). По некоторому сигналу void A::foo() нужно, чтобы класс A уничтожился, а вместо него создался класс B. Какие будут предложения? Можно немного видоизменять задачу, но чтобы суть оставалась.
|
|
Отправлено: 12:56, 31-10-2005 |
редкий гость Сообщения: 1696
|
Профиль | Сайт | Отправить PM | Цитировать pva
Сделать враппер? По-моему, самое логичное решение. Т.е. для пользователя это один объект нкжного интерфейса, а внутри он переадресовывает все вызовы требуемому объекту. Просто и надёжно. Второй вариант, если на объектр хранится всего один указатель (например как поле какого-то объекта), то можно, например, при создании этого обхекта дать ему указатель на этот указатель, и когда он пожелавет заменить себя на B, пусть просто удалиться, а по указателю запишет адрес ново-созданного B. Просто и очень ненадёжно. Вариант третий, написать свой аллокатор (или перегрузить operator new/delete), что бы он выделял памяти достаточно под объекты как типа A, так и типа B. Тогда при необходимости удалиться можно вызвать на себя деструктор, и на своём же старом месте с помощью placement new создать объект класса B. По идее, если объекты наследуют одинаковые интерфейсы (лучше если в одинаковом порядке), то будет работать. Сложно, да и нафиг нужно. |
------- Отправлено: 19:40, 31-10-2005 | #2 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Ветеран Сообщения: 1180
|
Профиль | Отправить PM | Цитировать Вопрос не в этом. Дело в том, что операция delete this вообще говоря противоречит смыслу. Перед вызовом деструктора объект уже не живёт, а его указатель используется, да ещё и виртуальной функцией.
использовать код вроде switch(action) {...} не хочется, т.к. объекты хранят разную информацию. class X {} class A : X {int n;virtual void foo();} class B : X {double f;} std::auto_ptr<X> px(new A()); void A::foo() { // пожелал заменить себя // стандартный аллокатор ::new выделит достаточно памяти px.reset(new B()); // A уже не существует, но используется его указатель // например: ++n; по идее здесь access violation } |
Отправлено: 10:39, 03-11-2005 | #3 |
редкий гость Сообщения: 1696
|
Профиль | Сайт | Отправить PM | Цитировать Цитата:
Другое дело, что после самоубийства в методе мы уже не можем обращаться к полям объекта. В общем, не вижу противоречий. |
|
------- Отправлено: 20:56, 03-11-2005 | #4 |
Ветеран Сообщения: 1180
|
Профиль | Отправить PM | Цитировать Так что делать? Прослеживать, чтобы A::foo() запускалась только там, где можно?
|
|
Отправлено: 13:21, 07-11-2005 | #5 |
Ветеран Сообщения: 1180
|
Профиль | Отправить PM | Цитировать Решил через очередь заданий
|
Отправлено: 10:20, 14-11-2005 | #6 |
редкий гость Сообщения: 1696
|
Профиль | Сайт | Отправить PM | Цитировать pva
Пардон, потерял тему, поэтому не отвечал. Как я уже сказал, я бы обернул вызовы методов A и B во враппер AB, который внутри вызвает методы соответствующего объекта. Опять же так и внешние ссылки отследить проще. Цитата:
|
|
------- Отправлено: 18:45, 14-11-2005 | #7 |
Ветеран Сообщения: 1180
|
Профиль | Отправить PM | Цитировать Можно код? Я не понял.
Очередь заданий: // класс задание или действие class TAction { public: virtual ~TAction() {} virtual void fire() = 0; }; // список заданий (exception-safe) class TActionList { typedef std::vector<TAction*>::iterator iter; std::vector<TAction*> fitems; void _remove(iter a, iter b) { for(iter c=a; a!=b; ++c) delete *c; fitems.erase(a,b); } public: ~TActionList() {clear();} void add(TAction* a) {fitems.push_back(a);} void remove(TAction* a) {_remove(std::remove(fitems.begin(), fitems.end(), a));} void clear() {_remove(fitems.begin(), fitems.end());} void fire() {for(iter a=fitems.begin(), b=fitems.end(); a!=b; ++b) (*a)->fire();} }; // класс, управляющий жизнью объектов // TObject::execute() можно вызывать только один раз при запуске программы class TObject { static TActionList fcleanup; static void processTasks(); static void cleanup() {fcleanup.fire(); fcleanup.clear();} public: static void execute(); static void registerCleanup(TAction* a) {fcleanup.add(a);} } TActionList TObject::fcleanup; void TObject::execute() { while (waitTask()) { processTasks(); // каким-нибудь образом вызывает A::foo(); cleanup(); // такой доступ к cleanup() гарантирует, что в стеке ничего от A:: не запущено } } ... // где-нибудь в программе: std::auto_ptr<A> behavior; void A::foo() { struct cleanup_A { void fire() { clog << "cleanup_A" << end;} cleanup_A(A* a) : fcleanup(a); private: std::auto_ptr<A> fcleanup; } std::auto_ptr<A> b(new B(...)); std::auto_ptr<cleanup_A> clean_a(new cleanup_A(behavior.get())); TObject::registerCleanup(clean_a.get()); clean_a.release(); // non-throwing behavior.release(); // non-throwing behavior = b; // non-throwing } Для полной картины, хорошо бы добавить A::unlink(), которая убирает связи ещё живого A с другими объектами. |
Отправлено: 13:11, 16-11-2005 | #8 |
Участник сейчас на форуме | Участник вне форума | Автор темы | Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
.NET - Нужны 2 класса на С# срочно. | Smile | Программирование и базы данных | 3 | 14-01-2010 09:18 | |
ПК класса «all-in-one»: оправдались ли ожидания? | OSZone News | Новости информационных технологий | 0 | 29-09-2009 02:30 | |
Сеть класса С. Вопросец... | clin | Microsoft Windows NT/2000/2003 | 8 | 07-09-2009 09:36 | |
Разное - [решено] регистрация класса | Shadow76 | Microsoft Windows 2000/XP | 6 | 04-06-2009 13:55 | |
* Теория * | C++ Доступ к членам класса через указатели | Kincajou | Программирование и базы данных | 6 | 30-07-2006 22:36 |
|