интерфейсы, реализация и базовый класс
От: Kluev  
Дата: 11.02.04 12:29
Оценка:
Размышлял тут на тему интерфейов и возникли некоторые вопросы которые хотелось бы обсудить.
Есть проблема совместить иерархию интерфейсных классов с иерархией классов-реализаций. Для примера имеем:
// базовый класс для обьектов
struct Object {
    virtual ~Object()    {}
};

struct IA {
    virtual void ia()    = 0;
};

struct IB : IA {
    virtual void ib()    = 0;
};

// реализация IA
struct CA : Object, IA {
    void ia() {}
};

// опс! это работать не будет IA входит в наследование дважды.
struct CB : CA, IB { // не работает
    virtual void ib() {}
};


В этом примере есть класс Object который кажется лишним, но он нужен т.к. некоторые классы наследуются только от него не используя интерфейсы.

Чтобы решить проблему с классом СВ можно все интерфейсные классы наследовать виртуально:
struct IA {
    virtual void ia()    = 0;
};

struct CA : Object, virtual IA {
    void ia() {}
};

struct IB : virtual IA {
    virtual void ib()    = 0;
};

struct CB : CA, virtual IB {
    virtual void ib() {}
};

Так все работает, но есть небольшая заморочка. В такой схеме получается что у интерфейсов нет общего базового класса, а хотелось бы его иметь чтобы не иметь гемора с передачей параметров. Т.е. как вариант можно все интерфейсы наследовать виртуально от Object и классы тоже
struct IA : virtual Object {
};

struct MyClass : virtual Object, virtual IA { // реализация
};

Но с другой стороны Object и так будет входить в иерархию классов только один раз, как корень всех классов реализаций (в этом случае у интерфейсов нет общего базового класса). Но тут можно учесть то что интерфейс сам по себе жить не может и реализуется только в составе класса базового от Object и до Object можно всегда достучатся через dynamic_cast.

Вот с этого места я в раздумьях как поступить?
1. Наследовать все виртуально от Object?
2. Наследовать реализации невиртуально от Object, а у интерфейсов нет общего класса?
3. Наследовать реализации невиртуально от Object и завести общий класс для интерфейсов?
Re: интерфейсы, реализация и базовый класс
От: Left2 Украина  
Дата: 11.02.04 13:22
Оценка:
Есть такой подход:

class CObject
{
};

class IA
{
};

class IB : public IA
{
};

template <class T>
class IA_Impl : public T
{
 // Реализация методов IA
};

class CA : public Object, IA_Impl<IA> 
{
   // Специфические для CA функции
};

class CB : public Object, IA_Impl<IB> 
{
   // Реализация только методов, добавленных в IB
   // Специфические для CB функции
};


Если от IB тоже будут наследовать интерейсы, можно добавить IB_Impl
Не всегда это удобно, но зато позволяет собирать реализацию для интерфейсов по кусочкам
Re[2]: интерфейсы, реализация и базовый класс
От: Kluev  
Дата: 11.02.04 13:49
Оценка:
Здравствуйте, Left2, Вы писали:

L>Есть такой подход:


L>
// поскипано
L>class CB : public Object, IA_Impl<IB> 
L>{
L>};
L>


Такой хак я знаю, но давно от него отказался. В этом случае прийдется все классы держать в хидерах и любое изменение приводит к пересборке всего проекта, а это не есть гуд (в большом проекте).
Re: интерфейсы, реализация и базовый класс
От: MaximE Великобритания  
Дата: 11.02.04 14:01
Оценка:
Kluev wrote:

> Размышлял тут на тему интерфейов и возникли некоторые вопросы которые хотелось бы обсудить.


[]

http://www.rsdn.ru/Forum/?mid=517249
Автор: Batiskaf
Дата: 24.01.04


--
Maxim Egorushkin
MetaCommunications Engineering
http://www.meta-comm.com/engineering/
Posted via RSDN NNTP Server 1.8 beta
Re[3]: интерфейсы, реализация и базовый класс
От: Left2 Украина  
Дата: 11.02.04 14:04
Оценка:
K>Такой хак я знаю, но давно от него отказался. В этом случае прийдется все классы держать в хидерах и любое изменение приводит к пересборке всего проекта, а это не есть гуд (в большом проекте).

Почему хак? Всё как бы честно
Не обязательно всю реализацию держать в хидерах
Функции — члены темплейтов могут вызывать конкретную реализацию, которая уже содердится в cpp-файлах
Хотя, конечно, усложнение налицо
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.