Одинаковые функции в разных интерфейсах...
От: The Lex Украина  
Дата: 06.06.01 13:36
Оценка:
Тут возникла не столько проблема, сколько неудобство: при использовании нескольких интерфейсов, имеющих одинаковые описания функций, для одного и того же компонента приходится извращаться в переопределении их описаний:

interface IX
{
virtual void SetThis(int this) = 0;
};

interface IY
{
virtual void SetThis(int this) = 0;
};

class CComp : public IX, public IY
{
virtual void SetThis(int this);
// Хм...
};

Нет ли каких предложений на эту тему?
Заранее благодарен...
Голь на выдумку хитра, однако...
Re: Одинаковые функции в разных интерфейсах...
От: IT Россия linq2db.com
Дата: 06.06.01 14:35
Оценка:
Попробуй макросы или шаблоны.
Если нам не помогут, то мы тоже никого не пощадим.
Re: Одинаковые функции в разных интерфейсах...
От: Alex Fedotov США  
Дата: 06.06.01 14:41
Оценка:
Здравствуйте The Lex, вы писали:

TL>Тут возникла не столько проблема, сколько неудобство: при использовании нескольких интерфейсов, имеющих одинаковые описания функций, для одного и того же компонента приходится извращаться в переопределении их описаний:


TL>interface IX

TL>{
TL> virtual void SetThis(int this) = 0;
TL>};

TL>interface IY

TL>{
TL> virtual void SetThis(int this) = 0;
TL>};

TL>class CComp : public IX, public IY

TL>{
TL> virtual void SetThis(int this);
TL> // Хм...
TL>};

TL>Нет ли каких предложений на эту тему?

TL>Заранее благодарен...

Я решал эту проблему так, когда она возникала:

class IXImpl : public IX
{
virtual void X_SetThis(int this) = 0;
virtual void SetThis(int this)
{ X_SetThis(this); }
};

class IYImpl : public IY
{
virtual void Y_SetThis(int this) = 0;
virtual void SetThis(int this)
{ Y_SetThis(this); }
};

class CComp : public IXImpl, public IYImpl
{
virtual void X_SetThis(int this);
virtual void Y_SetThis(int this);
// Хм...
};
-- Alex Fedotov
Re: Одинаковые функции в разных интерфейсах...
От: sanyvaa  
Дата: 06.06.01 15:33
Оценка:
Здравствуйте The Lex, вы писали:

TL>Тут возникла не столько проблема, сколько неудобство: при использовании нескольких интерфейсов, имеющих одинаковые описания функций, для одного и того же компонента приходится извращаться в переопределении их описаний:


TL>interface IX

TL>{
TL> virtual void SetThis(int this) = 0;
TL>};

TL>interface IY

TL>{
TL> virtual void SetThis(int this) = 0;
TL>};

TL>class CComp : public IX, public IY

TL>{
TL> virtual void SetThis(int this);
TL> // Хм...
TL>};

TL>Нет ли каких предложений на эту тему?

TL>Заранее благодарен...


Может быть вам будет удобнее использовать реализацию интерфейсов в виде вложенных классов и макрос METHOD_PROLOGUE, как это используется при создании COM-интерфейсов средствами MFC. А вообще-то СОМ-сервера "ручками" писать неудобно, лучше использовать тот же MFC или ATL...

----------
SANY
Re: Одинаковые функции в разных интерфейсах...
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.06.01 20:23
Оценка:
Что-то типа:
interface IX
{
virtual void SetThis(int this) = 0;
};

interface IY
{
virtual void SetThis(int this) = 0;
};

class IX_Impl : public IX
{
void SetThis(int this){ реализация IX }
}

class IY_Impl : public IY
{
void SetThis(int this){ реализация IY }
}

class CComp : public IX_Impl, public IY_Impl
{
QueryInterface(REFIID iid, void ** pp)
{
if(iid == {xxx-IX-xxx})
pp = (void**)&(IX_Impl*)this;
else if(iid == {xxx-IY-xxx})
pp = (void**)&(IY_Impl*)this;
...
}
};

Но, на ATL-действительно проще.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Одинаковые функции в разных интерфейсах...
От: Odissey Россия http://malgarr.blogspot.com/
Дата: 07.06.01 02:19
Оценка:
Здравствуйте The Lex, вы писали:

TL>Тут возникла не столько проблема, сколько неудобство: при использовании нескольких интерфейсов, имеющих одинаковые описания функций, для одного и того же компонента приходится извращаться в переопределении их описаний:


TL>Нет ли каких предложений на эту тему?

TL>Заранее благодарен...

Могу кинуть примеры из Трельсена, где разбирается эта ситуация. А то сам книжку поищи —
Трельсен "Модель COM и применение ATL 3.0"
Re[2]: Одинаковые функции в разных интерфейсах...
От: sanyvaa  
Дата: 07.06.01 06:05
Оценка:
Здравствуйте VladD2, вы писали:

VD>Что-то типа:

VD>interface IX
VD>{
VD> virtual void SetThis(int this) = 0;
VD>};

VD>interface IY

VD>{
VD> virtual void SetThis(int this) = 0;
VD>};

VD>class IX_Impl : public IX

VD>{
VD> void SetThis(int this){ реализация IX }
VD>}

VD>class IY_Impl : public IY

VD>{
VD> void SetThis(int this){ реализация IY }
VD>}

VD>class CComp : public IX_Impl, public IY_Impl

VD>{
VD> QueryInterface(REFIID iid, void ** pp)
VD> {
VD> if(iid == {xxx-IX-xxx})
VD> pp = (void**)&(IX_Impl*)this;
VD> else if(iid == {xxx-IY-xxx})
VD> pp = (void**)&(IY_Impl*)this;
VD> ...
VD> }
VD>};

Твой пример не совсем корректен (или даже совсем не корректен). По теории COM, если вы получаете какой-то интерфейс от объекта, реализующего несколько интерфейсов, то по этому указателю можно запросить все остальные интерфейсы, реализуемые объектом. А как в вашем примере класс IX_Impl реализует QueryInterface(), чтобы вернуть интерфейс IY ? В данном случае это невозможно, поэтому-то в MFC-шной реализации и используются вложеннные классы, что-то типа:

class CComp : public IX_Impl, public IY_Impl
{
class IX_Impl : public IX
{
void SetThis(int this){ реализация IX } ;

AddRef() {
METHOD_PROLOGUE(CComp , IX_Impl )
return pThis->ExternalAddRef();
};

Release()
{
METHOD_PROLOGUE(CComp , IY_Impl )
return pThis->ExternalAddRef();
}

QueryInterface(){...};
}

class IY_Impl : public IY
{
void SetThis(int this){ реализация IY }
AddRef() {...};
Release(){...};
QueryInterface(){...};
}
}
Re[2]: Одинаковые функции в разных интерфейсах...
От: sanyvaa  
Дата: 07.06.01 06:10
Оценка:
Здравствуйте VladD2, вы писали:

VD>Что-то типа:

VD>interface IX
VD>{
VD> virtual void SetThis(int this) = 0;
VD>};

VD>interface IY

VD>{
VD> virtual void SetThis(int this) = 0;
VD>};

VD>class IX_Impl : public IX

VD>{
VD> void SetThis(int this){ реализация IX }
VD>}

VD>class IY_Impl : public IY

VD>{
VD> void SetThis(int this){ реализация IY }
VD>}

VD>class CComp : public IX_Impl, public IY_Impl

VD>{
VD> QueryInterface(REFIID iid, void ** pp)
VD> {
VD> if(iid == {xxx-IX-xxx})
VD> pp = (void**)&(IX_Impl*)this;
VD> else if(iid == {xxx-IY-xxx})
VD> pp = (void**)&(IY_Impl*)this;
VD> ...
VD> }
VD>};

Твой пример не совсем корректен (или даже совсем не корректен). По теории COM, если вы получаете какой-то интерфейс от объекта, реализующего несколько интерфейсов, то по этому указателю можно запросить все остальные интерфейсы, реализуемые объектом. А как в вашем примере класс IX_Impl реализует QueryInterface(), чтобы вернуть интерфейс IY ? В данном случае это невозможно, поэтому-то в MFC-шной реализации и используются вложеннные классы, что-то типа:

class CComp : public IX_Impl, public IY_Impl
{

class IX_Impl : public IX
{
void SetThis(int this){ реализация IX } ;

AddRef() {
METHOD_PROLOGUE(CComp , IX_Impl )
return pThis->ExternalAddRef();
};

Release()
{
METHOD_PROLOGUE(CComp , IX_Impl )
return pThis->ExternalAddRef();
}

QueryInterface()
{
METHOD_PROLOGUE(CComp , IX_Impl )
return pThis->ExternalQueryInterface();
}

}

class IY_Impl : public IY
{
/тоже самое/
}
}

Так как в случае вложенного класса можно без проблем получить указатель pThis на внешний класс и переслать ему вызовы QueryInterface().

-------------
regards, SANY
Re[2]: Одинаковые функции в разных интерфейсах...
От: The Lex Украина  
Дата: 07.06.01 06:48
Оценка:
Здравствуйте IT, вы писали:

IT>Попробуй макросы или шаблоны.


Макросы и шаблоны — это хорошо, когда понятна суть того, что они делают. Меня интересует имеено суть того...
Голь на выдумку хитра, однако...
Re[2]: Одинаковые функции в разных интерфейсах...
От: The Lex Украина  
Дата: 07.06.01 06:52
Оценка:
Здравствуйте Alex Fedotov, вы писали:

AF>Я решал эту проблему так, когда она возникала:


AF>class IXImpl : public IX

AF>{
AF> virtual void X_SetThis(int this) = 0;
AF> virtual void SetThis(int this)
AF> { X_SetThis(this); }
AF>};

AF>class IYImpl : public IY

AF>{
AF> virtual void Y_SetThis(int this) = 0;
AF> virtual void SetThis(int this)
AF> { Y_SetThis(this); }
AF>};

AF>class CComp : public IXImpl, public IYImpl

AF>{
AF> virtual void X_SetThis(int this);
AF> virtual void Y_SetThis(int this);
AF> // Хм...
AF>};

Хм... Это довольно интересно... Спасибо.
Голь на выдумку хитра, однако...
Re[2]: Одинаковые функции в разных интерфейсах...
От: The Lex Украина  
Дата: 07.06.01 06:57
Оценка:
Здравствуйте sanyvaa, вы писали:

S>Может быть вам будет удобнее использовать реализацию интерфейсов в виде вложенных классов и макрос METHOD_PROLOGUE, как это используется при создании COM-интерфейсов средствами MFC. А вообще-то СОМ-сервера "ручками" писать неудобно, лучше использовать тот же MFC или ATL...


По-поводу того, что "ручками писать неудобно" у меня есть свое мнение: понимание сути процесса ведет к использованию средств, облегчающих разработку. Для использование дополнительных средств разработки (MFC, ATL) необходимо понимание как сути "нижнего уровня", так и "надстройки". При этом методы как "нижнего", так и "верхнего" уровней могут быть использованы в других случаях довольно эффективно. Но для этого их необходимо понимать.

Меня интересует именно "нижний уровень" — чистые языковые средства.
Голь на выдумку хитра, однако...
Re[2]: Одинаковые функции в разных интерфейсах...
От: The Lex Украина  
Дата: 07.06.01 06:59
Оценка:
Здравствуйте VladD2, вы писали:

VD>Что-то типа:

VD>interface IX
VD>{
VD> virtual void SetThis(int this) = 0;
VD>};

VD>interface IY

VD>{
VD> virtual void SetThis(int this) = 0;
VD>};

VD>class IX_Impl : public IX

VD>{
VD> void SetThis(int this){ реализация IX }
VD>}

VD>class IY_Impl : public IY

VD>{
VD> void SetThis(int this){ реализация IY }
VD>}

VD>class CComp : public IX_Impl, public IY_Impl

VD>{
VD> QueryInterface(REFIID iid, void ** pp)
VD> {
VD> if(iid == {xxx-IX-xxx})
VD> pp = (void**)&(IX_Impl*)this;
VD> else if(iid == {xxx-IY-xxx})
VD> pp = (void**)&(IY_Impl*)this;
VD> ...
VD> }
VD>};

VD>Но, на ATL-действительно проще.


ATL — это, наверно хорошо. Но в данном случае Ваш вариант не подходит, так как реализации SetThis(...) должны находиться именно в CComp — в классе компонента.
Голь на выдумку хитра, однако...
Re[3]: Одинаковые функции в разных интерфейсах...
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.06.01 10:41
Оценка:
S>Твой пример не совсем корректен (или даже совсем не корректен). По теории COM, если вы получаете какой-то интерфейс от объекта, реализующего несколько интерфейсов, то по этому указателю можно запросить все остальные интерфейсы, реализуемые объектом. А как в вашем примере класс IX_Impl реализует QueryInterface(), чтобы вернуть интерфейс IY ? В данном случае это невозможно, поэтому-то в MFC-шной реализации и используются вложеннные классы, что-то типа:

Ну, я бы сказал не полный. Что мне здесь полный код QI во всех классах прописывать?
Если юзать ATL, то проблем не возникает потому, как IUnknown реализуется один раз для всех классов. Так что чем велосипед изобретать лучше берите ATL и смотрите как IDispatchIml<> реализован.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Одинаковые функции в разных интерфейсах...
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.06.01 10:50
Оценка:
S>Так как в случае вложенного класса можно без проблем получить указатель pThis на внешний класс и переслать ему вызовы QueryInterface().

Тоже мне проблема this суперкласса получить. Есть много способов это сделать. ATL-щики, те вообще тип конечного суперкласса как темплэйтный параметр передают и потом делают так:
T * pT = (T*)this;
pT->SomeSuperCall();

При этом и указатель на this супера не нужен.

Так что повторюсь... чем велосипеды изобретать, лучше изучать код профи (ATL на пример). А лучший способ обучения реализация своих идей их средствами и дотошное (с применением отладчика) сканирование их кода.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Одинаковые функции в разных интерфейсах...
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.06.01 10:56
Оценка:
Здравствуйте The Lex.

Подходит, но имплы надо объявить как тэмплэйты. С ATL это делается за пару секунд. Подробнее смотри второй ответ sanyvaa-у и IDispatchImpl<>. Лично у нас каким макаром горы кода написано и все работает.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Одинаковые функции в разных интерфейсах...
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.06.01 10:58
Оценка:
Здравствуйте Odissey, вы писали:

O>Могу кинуть примеры из Трельсена, где разбирается эта ситуация. А то сам книжку поищи —

O>Трельсен "Модель COM и применение ATL 3.0"

Кинь. А то из головы описывать сложновато. Я чувствую народ не прочувствовал ;).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Одинаковые функции в разных интерфейсах...
От: Odissey Россия http://malgarr.blogspot.com/
Дата: 07.06.01 11:18
Оценка:
Здравствуйте VladD2, вы писали:

VD>Здравствуйте Odissey, вы писали:


O>>Могу кинуть примеры из Трельсена, где разбирается эта ситуация. А то сам книжку поищи —

O>>Трельсен "Модель COM и применение ATL 3.0"

VD>Кинь. А то из головы описывать сложновато. Я чувствую народ не прочувствовал ;).


в этом примере метод Draw() есть и в IDraw и в I3DRender

это *.h

class Co3DHexagon : public IDraw
{
public:
Co3DHexagon();
virtual ~Co3DHexagon();

// IUnknown
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
STDMETHODIMP QueryInterface(REFIID riid, void** ppv);

// IDraw::Draw
STDMETHODIMP Draw();

// IShapeID
STDMETHODIMP ID(int id);

// I3DRender <<< Обертка для второго интерфейса !!!!!!
struct I3DRenderImpl : public I3DRender
{
// IUnknown methods.
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
STDMETHODIMP QueryInterface(REFIID riid, void** ppv);

// IDraw methods.
STDMETHODIMP Draw();

// Pointer to parent.
Co3DHexagon* m_pParent;
};

private:
I3DRenderImpl m_3dRenderImpl;
ULONG m_refCount;
};

а это *.cpp

Co3DHexagon::Co3DHexagon()
{
m_refCount = 0;
m_3dRenderImpl.m_pParent = this;
g_objCount++;
}

Co3DHexagon::~Co3DHexagon()
{
g_objCount--;
}

STDMETHODIMP_(ULONG) Co3DHexagon::AddRef()
{
return ++m_refCount;
}

STDMETHODIMP_(ULONG) Co3DHexagon::Release()
{
if(--m_refCount == 0)
{
delete this;
return 0;
}
return m_refCount;
}

STDMETHODIMP Co3DHexagon::QueryInterface(REFIID riid, void** ppv)
{
if (riid == IID_IUnknown)
{
*ppv = (IUnknown*)(IDraw*)this;
}
else if (riid == IID_IDraw)
{
*ppv = (IDraw*)this;
}
else if(riid == IID_I3DRender)
{
*ppv = (I3DRender*)&m_3dRenderImpl;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}

((IUnknown*)(*ppv))->AddRef();
return S_OK;
}

STDMETHODIMP Co3DHexagon::Draw()
{
MessageBox(NULL, "Drawing a boring 2D hexagon", "Outer Class", MB_OK);
return S_OK;
}

//////////////////////////////////////////////////////////////////////
// I3DRenderImpl
STDMETHODIMP_(ULONG) Co3DHexagon::I3DRenderImpl::AddRef()
{
return m_pParent->AddRef();
}

STDMETHODIMP_(ULONG) Co3DHexagon::I3DRenderImpl::Release()
{
return m_pParent->Release();
}

STDMETHODIMP Co3DHexagon::I3DRenderImpl::QueryInterface(REFIID riid, void** ppv)
{
return m_pParent->QueryInterface(riid, ppv);
}

STDMETHODIMP Co3DHexagon::I3DRenderImpl::Draw() // Из обертки !!!!
{
MessageBox(NULL, "Drawing a lovely 3D hexagon", "Inner Class", MB_OK);
return S_OK;
}

вариант для ATL как я понял не интересует
Re: Одинаковые функции в разных интерфейсах...
От: Vlad_Zaharov  
Дата: 07.06.01 11:51
Оценка:
Здравствуйте The Lex, вы писали:

TL>Тут возникла не столько проблема, сколько неудобство: при использовании нескольких интерфейсов, имеющих одинаковые описания функций, для одного и того же компонента приходится извращаться в переопределении их описаний:


TL>interface IX

TL>{
TL> virtual void SetThis(int this) = 0;
TL>};

TL>interface IY

TL>{
TL> virtual void SetThis(int this) = 0;
TL>};

TL>class CComp : public IX, public IY

TL>{
TL> virtual void SetThis(int this);
TL> // Хм...
TL>};

TL>Нет ли каких предложений на эту тему?

TL>Заранее благодарен...

а не проще ли
class CIX : public IX
{
virtual void SetThis(int this){...};
};

class CIY : public IY
{
virtual void SetThis(int this){...};
};
Re: Одинаковые функции в разных интерфейсах...
От: Vlad_Zaharov  
Дата: 07.06.01 11:53
Оценка:
Здравствуйте The Lex, вы писали:

TL>Тут возникла не столько проблема, сколько неудобство: при использовании нескольких интерфейсов, имеющих одинаковые описания функций, для одного и того же компонента приходится извращаться в переопределении их описаний:


TL>interface IX

TL>{
TL> virtual void SetThis(int this) = 0;
TL>};

TL>interface IY

TL>{
TL> virtual void SetThis(int this) = 0;
TL>};

TL>class CComp : public IX, public IY

TL>{
TL> virtual void SetThis(int this);
TL> // Хм...
TL>};

TL>Нет ли каких предложений на эту тему?

TL>Заранее благодарен...

а не проще ли:
class CIX : public IX
{
virtual void SetThis(int this){...};
};

class CIY : public IY
{
virtual void SetThis(int this){...};
};


class CComp
{
CIX m_IX;
CIY m_IY;
};
Re[4]: Одинаковые функции в разных интерфейсах...
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.06.01 12:05
Оценка:
Здравствуйте ALL.

O>вариант для ATL как я понял не интересует


Не ужели велосипед должен быть обязательно самопальным?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.