Идея функционального замыкания заключается в реализации кода типа.
Инициализация
Выполнение
Деинициализация
Данный тип встречается часто особенно. Например, открыть записать закрыть файл. Или открыть контекст устройства вывести в контекст закрыть. Данный тип кода встречается на каждом шагу. Мы постоянно отрываем потом используем а потом. вот в последних действиях может и быть ошибка. Забыть закрыть что то это нормально. Для программиста, а для системы болезненно. Вот мы с Вами и посмотрим, какими методами можно этого избежать. Первый метод это использовать конструктор и деструктор класса. В конструкторе мы открываем, а в деструкторе закрываем. Давайте посмотрим, как можно из хотя из этой идеи создать класс для доступа к 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;
}
}
При разрушении класса пройдет закрытие указателя. Это может произойти при выходе за область видимости например из функции в которой он объявлен или при удалении динамического объекта.