несколько реализаций IDispatch в одном CoClass'е
От: Аноним  
Дата: 21.01.05 14:55
Оценка:
Предположим, класс реализет несколько интерфейсов.
class I1: public IDispatch {...}
class I2: public IDispatch {...}
class CImpl : public СImplementI1, public СImplementI2 {...}

Задача: нужно для каждого интерфеса класса выдать соответствующий ему IDispatch
вот так:

I1 *pI1;
//
...здесь создаем объект типа CImpl, присваиваем pI1 указатель на I1 из объекта
//
I2 *pI2;
pI2->QueryInterface(IID_I2, (void**)pI2);
IDispatch pDisp1;
pI1->QueryInterface(IID_IDispatch, (void**)pDisp1);
IDispatch pDisp2;
pI2->QueryInterface(IID_IDispatch, (void**)pDisp2);

в итоге, как ни крути pDisp1==pDisp2;
потому что в CImpl есть только один виртуальный метод QueryInterface, и сказать ему, из какого интерфеса (I1 или I2) хотят получить IDispatch нет никакой возможности.

В то же время, если использовать аггрегацию, то подобный прием проходит. Потому что существует 2 объекта, 2 разных vtable, и соответственно 2 QueryInterface.

ИМХО, это несправедливо, потому что из-за IDispatch я должен отказываться от множественного наследования.
Может, кто-нибудь знает как побороть проблему?
Re: несколько реализаций IDispatch в одном CoClass'е
От: more  
Дата: 21.01.05 15:24
Оценка:
А>IDispatch pDisp1;
А>pI1->QueryInterface(IID_IDispatch, (void**)pDisp1);
А>IDispatch pDisp2;
А>pI2->QueryInterface(IID_IDispatch, (void**)pDisp2);

извиняюсь, на самом деле вот так:

IDispatch *pDisp1;
pI1->QueryInterface(IID_IDispatch, (void**)pDisp1);
IDispatch *pDisp2;
pI2->QueryInterface(IID_IDispatch, (void**)pDisp2);
Re: несколько реализаций IDispatch в одном CoClass'е
От: ssm Россия  
Дата: 21.01.05 15:45
Оценка:
Здравствуйте, Аноним, Вы писали:

А>в итоге, как ни крути pDisp1==pDisp2;

А>потому что в CImpl есть только один виртуальный метод QueryInterface, и сказать ему, из какого интерфеса (I1 или I2) хотят получить IDispatch нет никакой возможности.

такая возможность как раз есть, отвлечемся от COM:


struct IDispatch
{
    virtual void QueryInterface(int, void**) = 0;
};

class I1 : public IDispatch 
{
public:
    virtual void QueryInterface(int, void**)
    {
    }
};

class I2: public IDispatch 
{
public:
    
    virtual void QueryInterface(int, void**)
    {
    }
};

class CImpl : public I1, public I2 
{
public:
    enum {IID_I1, IID_I2};

    virtual void QueryInterface(int iid, void**)
    {        
        if(iid == IID_I1)
        {
            I1::QueryInterface(iid, 0);
        }
        else if(iid == IID_I2)
        {
            I2::QueryInterface(iid, 0);            
        }    
    }

};


int main() 
{ 
    CImpl *p = new CImpl();
    p->QueryInterface(CImpl::IID_I1, 0);
    p->QueryInterface(CImpl::IID_I2, 0);

    return 0; 
}


тоесть пусть CImpl сам решает, по переданному идентификатору, куда диспачить вызов дальше
Re: несколько реализаций IDispatch в одном CoClass'е
От: Vi2 Удмуртия http://www.adem.ru
Дата: 24.01.05 05:19
Оценка: 6 (2)
Здравствуйте, Аноним, Вы писали:

А>...потому что в CImpl есть только один виртуальный метод QueryInterface, и сказать ему, из какого интерфеса (I1 или I2) хотят получить IDispatch нет никакой возможности.

А>В то же время, если использовать агрегацию, то подобный прием проходит. Потому что существует 2 объекта, 2 разных vtable, и соответственно 2 QueryInterface.

Это обманчивое представление. И агрегация не предоставляет вариантов для QueryInterface(IID_IDispatch), потому что внутренний объект должен переадресовать запрос QueryInterface внешнему. Так что схемы похожи и для твоего случая, и для агрегации — хоть и есть две различные реализации IDispatch, работать реально будет только одна. Та, которую вернет IUnknown::QueryInterface(IID_IDispatch) на любом интерфейсном указателе объекта.

А>ИМХО, это несправедливо, потому что из-за IDispatch я должен отказываться от множественного наследования.

А>Может, кто-нибудь знает как побороть проблему?

Не использовать IDispatch, т.к. это интерфейс, содержащий в самом себе противоречие: своими методами он описывает нечто, совершенно отличное от него самого, т.е. совершенно другой интерфейс. Или, другими словами, интерфейс IDispatch должен описывать методы (всего) объекта как целого.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.