Как не забыть упомянуть все мемберы объекта

  !   Данная информация предназначена только только для 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);
Advanced

CX_ALL_MEMBERS_LIKE дополнительно позволяет проверять вызов методов и выбирать мемберы регулярными выражениями. Синтаксис

CX_ALL_MEMBERS_LIKE(
    CClass
    functions|data
    plus|sans super
    [matching preg CX_SZ "..."])

где

  • CClass- проверяемый генерик класс указывается всегда даже если текущийтип мемберов
    • functions- проверять только методы
    • data- проверять только данныевключать ли родительские классы
    • plus super- включать все вплоть до object
    • 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");
Проблемы
  • Для методов не детектируется приватность. Использоватьfunctions plus super без указания ограничивающиего выбор preg практически не возможно (не выйдет упомянуть приватных матодов базового класса)
Приватные мемберы

Только CX_ALL_MEMBERS проверяет приватные (m_, _m_) мемберы и только текущего класса но не базовых классов естественно. Директива достаточно сообразительна чтобы игнорировать указатели на Ui в любом случае.

CX_ALL_MEMBERS_OF отслеживает только проперти (x_, _x_) и всегда пропускает все остальное.

Все директивы ориентируются только по префиксам мемберов. Они не отслеживают public: private: метки и не совместимы с приватными x-пропертями, которые как правило не рекомендуется применять вообще.