C++: как унаследоваться одновременно от базового класса и «интерфейса» при этом если оба они имеют общий «интерфейс»? Глоссарий: интерфейсом будем считать класс с чисто виртуальными функциями без состояния.
Допустим есть некий базовый интерфейс. От него наследуются другие интерфейсы. От них - рабочие классы. Примерно так:struct block_i
{
virtual ~block_i() = default;
virtual bool is_done() const = 0;
//...
};
template
struct consumer_block_i : public block_i
{
virtual void register_producer(producer_block_i&) = 0;
//...
};
template
struct action_block : public consumer_block_i
{
virtual bool is_done() const override { return false; }
virtual void register_producer(producer_block_i&) override {}
//...
};
Таких классов как action_block несколько, и все они содержат в том числе некий одинаковый код. Хотелось бы поместить его в базовый класс, допустим block_base, унаследовать его от block_i. чтобы получилось примерно так:struct block_base : public block_i
{
virtual bool is_done() const override { return false; }
};
template
class action_block
: public virtual block_base
, public virtual consumer_block_i
{
virtual void register_producer(producer_block_i&) override {}
//...
};
Но сделать так в C++ я не могу (ну или не знаю как) - получаю ошибку компиляции. В C# так сделать можно:interface IBlock
{
bool IsDone();
}
interface IConsumer : IBlock
{
void RegisterProducer(IProducer producer);
}
class BlockBase : IBlock
{
public bool IsDone() { return false; }
}
class Consumer : BlockBase, IConsumer
{
private IProducer producer_;
public void RegisterProducer(IProducer producer) { producer_ = producer; }
}
Вопрос: как реализовать такое же на C++? Если это возможно разумеется. В интерфейсы помещать некие дефолтные реализации не хочется.

21 Авг 2019 в 07:01
214 +1
1
Ответы
1

В C++ нет возможности множественного наследования от виртуальных базовых классов с общими функциями. Однако, можно достичь подобного эффекта, используя механизм наследования шаблонов (CRTP - Curiously Recurring Template Pattern).

В вашем случае, вы можете определить шаблонный класс block_base, который будет предоставлять общий код для классов, наследующихся от него. Примерно так:

template <class T>
struct block_base
{
bool is_done() const { return false; }
};
template <class T>
struct consumer_block_i : public block_base<T>
{
void register_producer(producer_block_i<T>& producer) {}
};
template<class T>
struct action_block : public consumer_block_i<T>
{
// дополнительный код...
};

Теперь класс action_block может наследоваться от consumer_block_i с общим кодом через шаблонный базовый класс block_base. В этом случае, код из block_base будет доступен внутри action_block.

Надеюсь, это поможет вам реализовать желаемую функциональность в вашем коде на C++.

20 Апр 2024 в 13:09
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир