Шаг 106 - Функциональное замыкание

Идея функционального замыкания заключается в реализации кода типа.

Инициализация
	Выполнение
Деинициализация

Данный тип встречается часто особенно. Например, открыть записать закрыть файл. Или открыть контекст устройства вывести в контекст закрыть. Данный тип кода встречается на каждом шагу. Мы постоянно отрываем потом используем а потом. вот в последних действиях может и быть ошибка. Забыть закрыть что то это нормально. Для программиста, а для системы болезненно. Вот мы с Вами и посмотрим, какими методами можно этого избежать. Первый метод это использовать конструктор и деструктор класса. В конструкторе мы открываем, а в деструкторе закрываем. Давайте посмотрим, как можно из хотя из этой идеи создать класс для доступа к COM порту на основе функций API. Слабое место в работе с портом, что после его открытия и использования нужно его закрыть, обязательно. Итак, создаем конструктор с параметрами. Никакого конструктора по умолчанию не будет.

class CComPort  
{
public:
	CComPort(LPCTSTR PortName,DWORD dwDesiredAccess,DWORD dwShareMode,
		LPSECURITY_ATTRIBUTES lpSecurityAttributes,
		DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,
		HANDLE hTemplateFile);
	virtual ~CComPort();
private:
	HANDLE ComPort; 
};

Код к конструктору и деструктору.

CComPort::CComPort(LPCTSTR PortName,DWORD dwDesiredAccess,
	DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,
	DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,
	HANDLE hTemplateFile)
{
	ComPort=CreateFile(PortName,dwDesiredAccess,dwShareMode,
		lpSecurityAttributes,dwCreationDisposition,
		dwFlagsAndAttributes,hTemplateFile);	
	if(ComPort==INVALID_HANDLE_VALUE)
		throw CString("Error Open");
}

CComPort::~CComPort()
{
	CloseHandle(ComPort);
}

Все что нам осталось определить некоторую виртуальную функцию для того, чтобы ее переопределить и встраивать код для работы с портом.

class CComPort  
{
public:
	virtual void WorkForPort();		// для работы с портом
	CComPort(LPCTSTR PortName,DWORD dwDesiredAccess,
		DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,
		DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,
		HANDLE hTemplateFile);
	virtual ~CComPort();
private:
	HANDLE ComPort; 	
};

Соответственно для использования этого класса нам нужно создать свой класс как наследник, переопределить эту функцию и все можно использовать. Обратите внимание на throw. Другого способа сообщить о неудачах в конструкторе вреда как нет.

#include "stdafx.h"
#include "ComPort.h"
#include "iostream.h"

class CMyCom : public CComPort
{
public:
	CMyCom(LPCTSTR PortName,DWORD dwDesiredAccess,DWORD dwShareMode,
		LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,
		DWORD dwFlagsAndAttributes,HANDLE hTemplateFile);
	void WorkForPort();
};

CMyCom::CMyCom(LPCTSTR PortName,DWORD dwDesiredAccess,DWORD dwShareMode,
		LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,
		DWORD dwFlagsAndAttributes,HANDLE hTemplateFile)
	:CComPort(PortName,dwDesiredAccess,dwShareMode,lpSecurityAttributes,
		dwCreationDisposition,dwFlagsAndAttributes,hTemplateFile)
{
}

void CMyCom::WorkForPort()
{
}

void main()
{
try
{
	CMyCom cm("LPT1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
	cm.WorkForPort(); 
}
catch(...)
{
	cout << "Error" << endl;
	return;
}
}

При разрушении класса пройдет закрытие указателя. Это может произойти при выходе за область видимости например из функции в которой он объявлен или при удалении динамического объекта.


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Каев Артем - 16.07.2001