Как спроектировать класс, который мне нужен, используя производный член класса в базовом классе?

#c #inheritance #combinations #virtual-functions #class-design

#c #наследование #комбинации #виртуальные функции #класс-дизайн

Вопрос:

Как правило, мы используем виртуальную функцию или композицию для разработки класса.Как я знаю, использование виртуальной функции сделает класс более структурированным; использовать композицию будет легко реализовать, но, возможно, написать больше повторяющегося кода. В этой ситуации: мне нужен анализатор, он будет использоваться для другого протокола.Теперь, я полагаю, что он будет использовать в A-протоколе с именем AParser, B-протокол с именем BParser, как показано ниже:

 class Parser {
 public:
  Parser(...);
  virtual ~Parser() = default;
  virtual bool Parse(...) = 0;

 private:
  // some attributes may be common
};

class AParser() : public Parser {
 public:
  AParser(...) : Parser() {};
  ~AParser() override = default;

  void bool Parser(...) override;
  inline AData Data() const { return AData_;}

 private:
  AData_;
}

class BParser() : public Parser {
 public:
  BParser(...) : Parser() {};
  ~BParser() override = default;

  void bool Parser(...) override;
  inline BData Data() const { return BData_;}

 private:
  BData_;
}
  

ну, AData и BData оба являются их собственными личными данными, их не следует помещать в базовый класс,

кроме того, не следует virtual AData/BData Data() = 0 (НЕПРАВИЛЬНО! ! !)

Итак, как спроектировать класс для решения проблемы? Теперь у меня есть две идеи, но я думаю, что они меня не удовлетворяют

  1. используйте static_cast<derived_class>(this)->derivedFunc() , во-первых, эта операция не элегантна, во-вторых, если я использую эту операцию, Inheritance encapsulation все еще имеет смысл?
  2. используйте общую функцию, например, virtual std::map<std::string, void *> GetData() = 0 , затем используйте member field name для получения сохраненных данных, но как использовать производные функции, все еще остается проблемой?

Я думаю, что этот вопрос может быть вопросом дизайна класса, не могли бы вы, пожалуйста, помочь мне ответить на вопрос?

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

1. В чем смысл этой GetData() функции? Почему вы не можете просто использовать свои анализаторы через их интерфейс базового класса? Возможно, вам не хватает GetData() в интерфейсе базового класса?

2. Совершенно непонятно, о чем вы просите. Даже в этом случае ваше описание неясно. Пример: «виртуальная функция или комбинация» Что такое «комбинация». Комбинация чего? Пожалуйста, делайте меньше описания всего фона и сосредоточьтесь на вещах, связанных с программированием. Кстати: ключевое слово «inline» неясно в этом контексте!

3. Нет, я не могу. Поскольку A B — это другой протокол, не удается спроектировать a GetData() , они возвращают другой тип, у другого типа есть свои собственные файлы. И у меня есть еще один вопрос: как использовать функцию производного класса в базовом классе ptr / ref, если функция не может быть спроектирована как виртуальная функция

4. Вам нужно вызывать getData из Parser amp; ? Может ли то, что нужно AData использовать AParser , и то, что нужно BData вместо этого использовать BParser , и то, что не волнует, не вызывать это?

5. @Klaus Я спрашиваю, как спроектировать класс в этой ситуации, теперь вам ясно? combination , извините, я имею в виду composition , он также может выполнить цель, но может написать больше дублирующего кода, я хочу знать, как достичь целевого использования наследования. почему я описываю так много предыстории? поскольку ответ на столь много связанных вопросов — «определить виртуальную функцию в базовом классе», я думаю, что конкретные проблемы требуют определенного фона, вы так не думаете?

Ответ №1:

Если два анализатора не возвращают одни и те же данные, у них нет связанного интерфейса и, вероятно, не должно быть общего базового класса.

Если они возвращают одни и те же данные, поместите GetData функцию в базовый класс. Или, что еще лучше, возвращайте данные непосредственно из Parse .