! | Данная информация предназначена только только для IT-специалистов по системной интеграции модулей БИОСОФТ-М. (см. Руководства пользователя к программным продуктам) |
Классическая проблема С/С++ и подобных: нужно не забыть присвоить, сравнить или сбросить все члены. Либо не все, а часть, но при добавлении новых данных в класс хочется предупреждения о необходимости его участия в общеобъектных операторах.
Просто пишем CX_ALL_MEMBERS в начале метода. И он заставит нас упомянуть как все данные текущего так и родительских классов.
Здесь как исключение правила о запрете макросов использование простого define помогает избежать ошибки в списке имен мемберов которые пришлось бы иначе продублировать:
void CUportSharedPortImpl::OnClearChannelPortState() { CX_ALL_MEMBERS; #define ASSIGN(member) { member = rNewUportSharedPort->member; } ref<CUportSharedPortImpl> rNewUportSharedPort; ASSIGN(x_nDeviceActualPortBaud); ASSIGN(x_sDeviceOpenError); ASSIGN(x_sDeviceVersionError); ASSIGN(x_sDeviceLastInputError); ASSIGN(x_nDeviceInputErrorCount); ASSIGN(x_sDeviceLastOutputError); ASSIGN(x_nDeviceOutputErrorCount); ASSIGN(x_sClientPortName); // skip non-data _m_bOneTimeInitUportSharedPortImplOk _m_sInitialSharedName; _m_interstructSharedPortState; }
Здесь все указанные проперти объекта будут успешно сброшены в значения по умолчанию объявленные при декларации класса.
Вариант CX_ALL_MEMBERS_OF(CMyClass) позволяет потребовать использования (или перечисления) всех мемберов заданного класса. Например конвертер между всеми данными двух разных классов:
// // Init Pi-Sample scalars from PexApi Sample data // CX_ALL_MEMBERS_OF(CPiSampleIfaceGp); CX_ALL_MEMBERS_OF(CPexApiSampleIfaceGp); rPiSample->x_sPiSampleModalityKey = sModalityKey; rPiSample->x_pathPiSampleAttachmentPrefix = rPexApiSample->x_pathAttachedMonitoringFile; rPiSample->x_bPiSamplePictureOnly = rPexApiSample->x_bPictureOnly; rPiSample->x_sPiSampleSendSampleInfoAttr = "//no-attr//"; rPiSample->x_sPiSampleAppData = rPexApiSample->x_unidefSaveAsBlob.Get().ExportAsBinary(); rPiSample->x_sPiSampleNoteForIndicatorRow = rPexApiSample->x_srtfNoteForIndicatorRow; rPiSample->x_sPiSampleNoteForPicture = rPexApiSample->x_srtfNoteForPicture; rPiSample->x_nPiSamplePictureSizeX = rPexApiSample->x_sizePicture.Get().w; rPiSample->x_nPiSamplePictureSizeY = rPexApiSample->x_sizePicture.Get().h; // missing assignments if (false) { // moving samples is not supported for Picom5 rPexApiSample->_x_pInsertAfterSample; // see FillIndicatorsToNewSample() rPexApiSample->x_rIndicatorList; } // // Fill indicator values (will copy x_rIndicatorList) // FillIndicatorsToNewSample( rPexApiSample, rPiSample);
CX_ALL_MEMBERS_LIKE дополнительно позволяет проверять вызов методов и выбирать мемберы регулярными выражениями. Синтаксис
CX_ALL_MEMBERS_LIKE( CClass functions|data plus|sans super [matching preg CX_SZ "..."])
где
CX_ALL_MEMBERS_LIKE( CDuSendGateImpl data sans super);
CX_ALL_MEMBERS_LIKE( CDuSendGateImpl functions sans super matching preg CX_SZ "^CalcXxx");
Только CX_ALL_MEMBERS проверяет приватные (m_, _m_) мемберы и только текущего класса но не базовых классов естественно. Директива достаточно сообразительна чтобы игнорировать указатели на Ui в любом случае.
CX_ALL_MEMBERS_OF отслеживает только проперти (x_, _x_) и всегда пропускает все остальное.
Все директивы ориентируются только по префиксам мемберов. Они не отслеживают public: private: метки и не совместимы с приватными x-пропертями, которые как правило не рекомендуется применять вообще.