Страницы

Поиск по вопросам

пятница, 27 декабря 2019 г.

Нужна критика по архитектуре классов в С++ для реализации таблиц ModBus

#cpp #наследование #шаблоны_с++ #modbus


Изучаю С++ и пишу библиотеку ModBus. Прошу полезного совета у Гуру по изменению архитектуры
в целом или ответить на конкретные вопросы в конце.

Я хочу с помощью шаблонов классов автоматически помещать любые пользовательские данные
в нужные таблицы данных ModBus с возвращением указателей на них.

class AlarmData_b01
{
    bool isAlarm;
    bool isCountActivate;
};

class MeintenanceData_b01
{
    bool isMeintenance;
    bool isCountActivate;
};

class MeintenanceData_f32
{
    unsigned short Id;
    unsigned long Time;
    float Rate;
};

AlarmData_b01       *AlarmData_b01_Alarm1_ptr       = InputBits::Add();
AlarmData_b01       *AlarmData_b01_Alarm2_ptr       = InputBits::Add();

MeintenanceData_b01 *AlarmData_b01_Meintenance1_ptr = InputBits::Add();
MeintenanceData_b01 *AlarmData_b01_Meintenance2_ptr = InputBits::Add();

MeintenanceData_f32 *AlarmData_f32_Meintenance1_ptr = InputRegs::Add();
MeintenanceData_f32 *AlarmData_f32_Meintenance2_ptr = InputRegs::Add();


Таким образом, для класса AlarmData  создается свой класс, регистрирующий все объекты
типа AlarmData. Тоже происходит и для класса MeintenanceData. Дискретные данные для
аварий помещаются в таблицу дискретных данных, а данные 16 бит помещаются в таблицу
регистров модбас.

Так же с помощью статического метода шаблонного класса можно задать адрес для созданной
области объектов в таблице ModBus.

InputBits::AddresSet(100);
InputBits::AddresSet(110);

InputRegs::AddresSet(100);


Таким образом будут формироваться таблицы данных, доступ к которым будет осуществляться
из вне сторонним устройством по интерфейсу RS485 и протоколу ModBus с заданием адреса
внутри посылки, указанного в моей программе с помощью AddresSet.

В начале мной был создан базовый шаблон класса

template 
class ModBusTables
{
    protected:

    static unsigned short   Addres;
    static unsigned short AreaSize;
    T_DataType *AreaData_ptr;

    ModBusTables();

    public:

    static void AddresSet(unsigned short ModBusAddres);
};


где

static unsigned short Addres        - Адрес области в таблице протокола Модбас
static unsigned short AreaSize      - Размер объектов в области
T_DataType            *AreaData_ptr - Тип для приведения указателя.


Так как в ModBus фактически существует только два типа данных: дискретные и ячейки
по 16 бит, то в параметрах данного шаблона будет либо bool либо unsigned short. Таким
образом AreaData_ptr - это указатель на тип данных конкретной таблицы ModBus, чтобы
можно было путешествовать по любым данным пользователя с помощью единого указателя.

Теперь приведу код шаблонного класса, который наследуется от одного из классов выше
и расскажу в чем заключается вопрос.

template  class ModBusTable;

template  class TT_Table>
class ModBusTable > : public TT_Table
{
    private:

    T_DataStruct AreaData;

    public:

    static T_DataStruct *Add()
    {
        ModBusTable *ModBusArea_ptr = new ModBusTable();

        T_DataStruct *Instance_Ptr = &ModBusArea_ptr->AreaData;

        ModBusTable >::AreaSize  = sizeof(ModBusArea_ptr->AreaData);
        ModBusArea_ptr->AreaData_ptr = (T_DataType *)Instance_Ptr;

        return Instance_Ptr;
    }
};


Главная задача данного шаблонного класса - создать свой объект в статическом методе,
зарегистрировать его в классе и возвратить указатель на данные пользовательского типа,
а так же преобразовать этот указатель в указатель AreaData_ptr объявленный в родительском
классе, чтобы с любыми пользовательскими типами можно было работать через указатель
на bool или unsigned short.

Теперь сам вопрос. Для того, чтобы не вбивать много параметров в шаблон для регистрирования
пользовательских данных в конкретной таблице ModBus, я применил наследование.

template  class InputBits:     public ModBusTable >  {};
template  class InputRegs:     public ModBusTable > {};
template  class OutputBits:    public ModBusTable > {};
template  class OutputRegs:    public ModBusTable > {};


Как логически объединить объекты классов

 InputBits и InputBits?


Объекты этих классов логически должны находится в одной таблице ModBus.

Существует ли способ заменить наследование в данном случае на что-то похожее на alias
template в С++11, чтобы создавать шаблон класса с новым именем InputBits по шаблону
ModBusTable? Так, чтобы работало выражение

 InputBits::Add() 


Приму любые советы по изменению архитектуры реализации данной задачи. Большое спасибо
за прочтение, внимание и ответы!
    


Ответы

Ответ 1



Для стандарта C++11 и новее можно было бы записать template struct Base{}; template using WrapperFirst = Base; template using WrapperSecond = Base; int main() { WrapperFirst a; WrapperSecond b; return 0; } Полного аналога alias template в C++03 построить не получится. Можно использовать шаблон структуры для частичного задания параметров базового шаблона. template struct Base{}; template struct Wrapper { typedef Base first; typedef Base second; }; int main() { Wrapper::first a; Wrapper::second b; return 0; }

Комментариев нет:

Отправить комментарий