×
Namespaces

Variants
Actions

Двухфазное конструирование

From Nokia Developer Wiki
Jump to: navigation, search
Article Metadata

Статья
Перевод:
Оригинал: Two-phase construction
Den123
Последнее редактирование: hamishwillee (09 Dec 2011)

Contents

Краткое описание

В C++ программировании под Symbian ОС концепция двухфазного конструирования используется для того чтобы гарантировано избежать сброса(leave) при создании и инициализации объектов перед тем, как поместить их в стек очистки (cleanup stack).

Причины возникновения проблемы

В C++ программировании под Symbian ОС указатели на объекты в динамической памяти сохраняются в стеке очистки. Это позволяет автоматически уничтожать объекты в случае возникновения сброса(leave). Вновь созданный объект помещается в стек очистки сразу же после создания и инициализации его с помощью конструктора. Согласно правилу, принятому в C++, после выделения памяти для объекта и до завершения выполнения конструктора объект не может быть сохранен в стеке очистки - вот почему возникновение сброса(leave) в это время недопустимо.

Решение проблемы и его последствия

Для того чтобы предотвратить возникновение исключительной ситуации до того, как объект помещен в стек очистки, нужно предотвратить возникновение исключения в конструкторе. Этого можно достигнуть, если реализовать двухфазный конструктор. Согласно концепции двухфазного конструирования, весь код, который может привести к сбросу, а так же все вызовы функций, который могут выбросить исключения выносят из конструктора в отдельный метод ConstructL() - он и является второй фазой конструирования. (Если предок содержит свой собственный метод ConstructL() - он должен быть явно вызван во время второй фазы конструирования объекта.) Вызов ConstructL() производится после создания объекта и помещения его в стек очистки. Для часто используемых классов вызов обычного конструктора и метода ConstructL() объединяют в одну специальную статическую функцию NewL(). Соответственно, для создания объекта нужно пользоваться этой функцией-фабрикой. Алгоритм работы этой функции следующий:

  • выделить память под объект
  • поместить его в стек очистки
  • выполнить вторую фазу конструирования (вызвать ConstructL())
  • извлечь созданный и проинициализированный объект из стека очистки

Если подразумевается дальнейшее использование вновь созданного объекта как локального (то есть он должен находится в стеке очистки все свое время жизни) реализуется дополнительная статическая функция NewLC() - алгоритм ее работы такой же как и у NewL() за одним исключением - вновь созданный объект не извлекается из стека очистки. Пример реализации ConstructL(), NewL(), NewLC():

	// Фаза #1 
CMyClass::CMyClass()
{
}
 
// Фаза #2
void CMyClass::ConstructL()
{
// Инициализация членов-данных
}
 
// Обе фазы создания вместе ...
CMyClass * CMyClass::NewL()
{
CMyClass * self = new (ELeave) CMyClass();
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self);
return self;
}
 
CMyClass * CMyClass::NewLC()
{
CMyClass * self = new (ELeave) CMyClass();
CleanupStack::PushL(self);
self->ConstructL();
return self;
}

В будущем...

Строго говоря, нет необходимости поддерживать двухфазное конструирование и стек очистки после того, как в Symbian появилась поддержка стандартных возможностей C++ и реализация сбросов(leaves) была переделана на обычные исключения. Exception/Leave - защищенный код гораздо проще реализовать в стандартном C++, однако Symbian продолжает поддерживать старый вариант реализации в целях совместимости. Когда-нибудь в будущем (будем надеется недалеком) мы сможем забыть эту изжившую себя концепцию и использовать стандартный C++ для разработки ПО под Symbian ОС.

This page was last modified on 9 December 2011, at 00:57.
70 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×