Join Now
Quality Rating:
  • Currently 0.0 / 5
(0.0 / 5 - 0 votes cast)
Expertise Level:
  • Currently 0.0 / 5
(0.0 / 5 - 0 votes cast)

This page was last modified 07:32, 14 July 2007.

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

From Forum Nokia Wiki

Перевод с английского, оригинальная статья находится здесь


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 ОС.

 
Powered by MediaWiki
     
     RDF Facets:
     
     
     qfnZtypeQUqfnTypeZCommunityContentQ
     qfnZtypeQUqfnTypeZWebpageQ
     qfnZtypeQUqfnTypeZWikiContentQ
     qmarsZlanguageQUxhttpE3aE2fE2fswE2enokiaE2ecomE2flanguageE2d1E2fenX