Наследование C++ и абстрактный класс

У меня абстрактный класс Interface. Интерфейс имеет метод read, который считывает и анализирует данные, и метод getData, который фактически возвращает проанализированные данные. Каждый интерфейс имеет объект Parser, который выполняет фактический синтаксический анализ. У парсера есть метод parse и геттеры для проанализированных данных. Классы USBInterface и SerialInterface наследуются от Interface.

Проблема:
Как я могу использовать другой парсер для USBInterface и SerialInterface?
Есть два парсера, USBParser и SerialParser, которые наследуются от Parser.

В моем текущем решении используется ссылка Parser в базовом классе Interface, который инициализируется в конструкторе интерфейса, но я не уверен, что это лучший подход.

 class Parser {
  public:
    Parser() {}
    int getData() {
      return data;
    }
  protected:
    int data;
};

class USBParser : public Parser {
  public:
    USBParser() {}
    bool parse(uint8_t *usbpacket) {
      data = usbpacket[1]; // Do the actual parsing here
      return true; // Return true if data is complete
    }
};

class SerialParser : public Parser {
  public:
    SerialParser() {}
    bool parse(uint8_t databyte) {
      data = databyte; // Do the actual parsing here
      return true; // Return true if data is complete
    }
};

class Interface {
  public:
    Interface(Parser &parser) : parser(parser) {}
    virtual bool read() = 0;
    int getData() {
      return parser.getData();
    }
  protected:
    Parser &parser;
};

class USBInterface : public Interface {
  public:
    USBInterface() : Interface(parser) {}
    bool read() {
      uint8_t usbpacket[4] = {0x00, 0x01, 0x02, 0x03}; // Read raw data from USB
      return parser.parse(usbpacket);
    }
  private:
    USBParser parser;
};

class SerialInterface : public Interface {
  public:
    SerialInterface() : Interface(parser) {}
    bool read() {
      uint8_t databyte = 0xFF; // Read raw data from serial port
      return parser.parse(databyte);
    }
  private:
    SerialParser parser;
};

int main() {
  USBInterface usb;
  SerialInterface serial;

  if (usb.read())
    println(usb.getData());
  if (serial.read())
    println(serial.getData());
}

Есть ли недостатки в моем подходе или есть способ лучше?

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

Serge 18.03.2018 14:41

@Serge: спасибо за ваш комментарий. Код, который я опубликовал, упрощен. Цель наследования - сделать абстракцию типа интерфейса. Остальная часть программы не должна заботиться о том, используется ли интерфейс USB или последовательный интерфейс, она просто должна иметь возможность читать данные с интерфейса.

tttapa 18.03.2018 14:45
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
84
1

Ответы 1

Ваш код мне кажется слишком сложным. Вместо этого вы можете использовать внедрение зависимостей, поскольку класс USBInterface зависит от USBParser, как разумный SerialInterface зависит от SerialParser. Это дает вам больше гибкости. Если у вас есть что-то вроде GenericParser, которое вы хотите использовать с USBInterface или SerialInterface.

class Parser {
  public:
    Parser() {}
    int getData() {
      return data;
    }
  protected:
    int data;
};

class USBParser : public Parser {
  public:
    USBParser() {}
    bool parse(uint8_t *usbpacket) {
      data = usbpacket[1]; // Do the actual parsing here
      return true; // Return true if data is complete
    }
};

class SerialParser : public Parser {
  public:
    SerialParser() {}
    bool parse(uint8_t databyte) {
      data = databyte; // Do the actual parsing here
      return true; // Return true if data is complete
    }
};

class Interface {
  public:
    Interface(Parser &parser) : parser(parser) {}
    virtual bool read() = 0;
    int getData() {
      return parser.getData();
    }
  protected:
    Parser &parser;
};

class USBInterface : public Interface {
  public:
    USBInterface(Parser &parser) : Interface(parser) {}
    bool read() {
      uint8_t usbpacket[4] = {0x00, 0x01, 0x02, 0x03}; // Read raw data from USB
      return parser.parse(usbpacket);
    }
};

class SerialInterface : public Interface {
  public:
    SerialInterface(Parser &parser) : Interface(parser) {}
    bool read() {
      uint8_t databyte = 0xFF; // Read raw data from serial port
      return parser.parse(databyte);
    }
};

int main() {
  USBParser usbParse
  USBInterface usb(usbParse);

  SerialParse serialParse;
  SerialInterface serial(serialParse);

  // GenericParse parse;
  // SerialInterface serial(parse);

  if (usb.read())
    println(usb.getData());
  if (serial.read())
    println(serial.getData());
}

Я вижу две непосредственные проблемы с этим подходом: USBParser::parse принимает указатель на массив байтов, а SerialParser::parse принимает один байт. Вдобавок ко всему, внедрение зависимостей не упрощает задачу: USB-интерфейс всегда использует USB-синтаксический анализатор, поэтому нет необходимости полагаться на то, что пользователь предоставит правильный синтаксический анализатор интерфейсу.

tttapa 18.03.2018 15:48

Другие вопросы по теме