#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
(НЕПРАВИЛЬНО! ! !)
Итак, как спроектировать класс для решения проблемы? Теперь у меня есть две идеи, но я думаю, что они меня не удовлетворяют
- используйте
static_cast<derived_class>(this)->derivedFunc()
, во-первых, эта операция не элегантна, во-вторых, если я использую эту операцию,Inheritance encapsulation
все еще имеет смысл? - используйте общую функцию, например,
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
.