| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Как объекту отказаться себя создавать? |
| Автор: Ibragim 4.10.2004, 01:00 |
| Всем ночи доброй. Такая ситуация: объект класса TMyClass сам решает при создании, есть ли подходящие условия для создания себя. Нужно, чтобы пользователь вызывал Create, а получал в ответ nil - и при этом не засорялась память и т.п. То есть хочется сделать так: constructor TMyClass.Create begin <...> if <нехочу создаваться> then self := nil; <...> end Как это правильно сделать, чтобы объект не создавался? Чтобы не выделялась память под переменные, и т.д. Заранее спасибо. |
| Автор: ДЫМ 4.10.2004, 01:32 |
| Попробуй сгенерировать "тихое исключение" if <нехочу создаваться> then Abort; |
| Автор: <Spawn> 4.10.2004, 05:05 | ||
Ibragim Примерно так:
|
| Автор: Ibragim 4.10.2004, 05:31 |
| Понятно... Будем пробовать. А так чтобы MyObject : TMyClass; begin MyObject := TMyClass.Create; if MyObjec = nil then .... никак сделать нельзя? Моим классом будут пользоваться другие, и невозможность создать объект класса у меня не исключение, а довольно стандартная ситуация. Предполагается, что пользователь моего класса обязательно проверит - создалось что-то или нет. И если просто возвращать nil вместо указателя на класс было бы самое оно. Но если нет - что ж, будем делать как советовали. В любом случае большое спасибо. |
| Автор: p0s0l 4.10.2004, 12:01 | ||||||
Можно сделать так:
Пример:
|
| Автор: Ibragim 4.10.2004, 14:02 |
| Спасибо. А что значит "предложенный способ не совсем правильный"? Какой способ? Твой? Тогда как совсем правильно? |
| Автор: p0s0l 4.10.2004, 15:17 | ||
| Ну да... То, что я предложил - не совсем правильно, потому что делается xor esi, esi... Это типа обмана компилятора. Щас в голову пришёл более правильный способ (вернее, в нём уже ничего неправильного не будет):
|
| Автор: <Spawn> 4.10.2004, 16:54 | ||
Кстати, интересный вопрос, вот такой код показывает что указатель при моем примере не инициализируется:
Но вот вопрос, а все ли данные от TObject корректно высвобождаются? Ни где про это не встречал описание, а всегда вызывал исключение в случае надобности, но правильно ли это p0s0l Ну тут даже и class function не нужно делать |
| Автор: p0s0l 4.10.2004, 18:01 | ||||||||||||||||
Если я в программе использую TBitmap, то в .exe (и в памяти) тоже будет код конструктора TBitmap.Create. Или я неправильно тебя понял... Объясни подробнее...
c := TMyClass.Create а не c := CreateMyClass; Тем более, что если применить приведённый подход, то никакой разницы ни для программиста, ни для юзера не будет. Ты разве почуствуешь разницу, Create - это конструктор или функция ? c := TMyClass.Create(..), и даже не задумаюсь, конструктор это или функция... И при таком подходе возможно то, чего хочет Ibragim: MyObject := TMyClass.Create; if MyObject = nil then ....
Сравни 2 варианта:
и второй вариант:
Чтобы окончательно развеять твои сомнения, можно заменить все эти манипуляции с AbortConstruction и Exit теми же исключениями, и ловить эти исключения в класс-функции Create... Тогда это будет выглядеть так:
|
| Автор: Ibragim 4.10.2004, 19:11 |
| Спасибо за интересные рассказы. В моем случае тормозов не будет - объемы выделения памяти не те. Хотя в контексте интересно. Тогда Гуру - хотите еще вопрос? Совсем сложный? Я даже и не спрашивал - но вдруг и так можно... Значит есть большое дерево классов, каждый класс, понятное дело, знает о своем родителе но ничего не ведает о потомке. Нужно обойти это дерево классов и создать наиболее подходящий объект по таким критериям: 1. единственный параметр - строка, получаемая в процессе работы (положим, из физического порта) 2. каждый класс может оценить по этой строке возможность создания экземпляра себя, и только саму возможность: могу создаться/не могу создаться 3. наиболее подходящий объект - это объект на наиболее удаленной от корня дерева ветке. 4. два объекта считаем одинаково подходящими, если они на одинаковом удалении от корня дерева - тогда одинаково хорошо любое решение. Для пользователя все должно выглядеть так: MyObject: TBaseClass; MyObject := TBaseClass.Create; а в MyObject - указатель на наиболее подходящий объект (ну или nil). прошу заметить из приведенного примера, что менеджера классов создавать нельзя - классы сами должны между собой "договориться" - какой объект создавать. |
| Автор: p0s0l 4.10.2004, 22:35 | ||||||||
Проще было бы сделать так:
Если же идти таким способом, как ты сказал, то всё равно надо делать что-то для того, чтобы знать, какие возможные классы можно создать... Имхо, легче всего это сделать, если объявить массив, в котором будут указаны всевозможные наследники. Пример. Есть такое дерево:
1 и 2 критерии будут проверяться функцией CheckString. Эта функция переписывается в каждом новом наследнике от TBaseClass и от его потомков. 3 и 4 критерии будут осуществляться в TBaseClass. Т.к. constructor TBaseClass сам по себе создаёт экземпляр TBaseClass (а нам надо создать наследника от него), то вместо конструктора надо использовать функцию/класс-функцию. И опять же, т.к. для 2 критерия надо проверять для каждого класса истинность условия, то придётся эту функцию проверки делать класс-функцией. Обычным методом сделать нельзя, т.к. самого экземпляра класса не существует еще (буди что временно создавать, но это криво).
Теперь если сделать так:
Есть способ без всяких массивов и других специальных прибамбасов. Только он опять же будет не совсем правильный... И к тому же, в любом случае, кроме объявления и реализации класса, надо делать ссылку на него (например, в глобальной переменной), иначе этот класс не будет участвовать в компиляции... |