Полиморфные handle
От: Ignoramus  
Дата: 06.12.05 13:07
Оценка:
Для сопряжения С++ библиотеки и VB программы решил для представления объектов С++ использовать хендлы и процедурно-ориенторованный API (подобно WinAPI). Хендлы предполагаю хранить в ассоциативном массиве, в парах целое число — объект.

Проблема в том, что объекты могут быть разных типов (классов). Варианты решения:

1) Поддерживать несколько таблиц хендлов — каждого типа отдельно, но тогда кол-во функций в API комбинаторно возрастает.

2) Различать тип объекта по хендлу. Например, разбить весь диапазон возможных значений хендлов на зарезервированные интервалы, и по интервалу определять тип, после чего делать соответствующий reinterpret_cast. Немного коряво и хаковато, зато типы могут быть совершенно независимы. (reinterpret_cast конечно хак, но система хендлов вообще — хак с точки зрения С++, а альтернативы ей я не вижу).

3) Наследовать все классы от одного интерфейса. Однако, если классы слишком разные, в этом обшем предке может вообще не оказаться полиморфных методов. Придется как-то даункастить, а этого хотелось бы избежать.

Какие решения практикует all?
Re: Полиморфные handle
От: Владислав Сомов http://forum.sukhoi.ru/forumdisplay.php?f=120
Дата: 06.12.05 13:14
Оценка:
Здравствуйте, Ignoramus, Вы писали:

I>Для сопряжения С++ библиотеки и VB программы решил для представления объектов С++ использовать хендлы и процедурно-ориенторованный API (подобно WinAPI). Хендлы предполагаю хранить в ассоциативном массиве, в парах целое число — объект.


I>Проблема в том, что объекты могут быть разных типов (классов). Варианты решения:


а) Хранить целое — объект, тип.
б) Хранить целое — объект-обертку, содержащую ссылку на объект.

Все это в одной таблице хендлов.
Re[2]: Полиморфные handle
От: Владислав Сомов http://forum.sukhoi.ru/forumdisplay.php?f=120
Дата: 06.12.05 13:15
Оценка:
Здравствуйте, Владислав Сомов, Вы писали:

ВС>б) Хранить целое — объект-обертку, содержащую ссылку на объект.


Это, по моему мнению, предпочтительней.
Re: Полиморфные handle
От: Angler Россия  
Дата: 06.12.05 13:18
Оценка: +2
Здравствуйте, Ignoramus, Вы писали:

I>Какие решения практикует all?


COM
Re[3]: Полиморфные handle
От: Ignoramus  
Дата: 06.12.05 13:28
Оценка:
Здравствуйте, Владислав Сомов, Вы писали:

ВС>Здравствуйте, Владислав Сомов, Вы писали:


ВС>>б) Хранить целое — объект-обертку, содержащую ссылку на объект.


ВС>Это, по моему мнению, предпочтительней.


А как из обертки получить нужный тип объекта? (а не просто void* или ISuperBase* )

Я представил себе это так (чем-то напоминает паттерн visitor"):

Обертка имеет интерфейс в виде набора методов, возращающих все возможные типы, но все они кроме одного возвращают 0 для конкретной реализации обертки. Обертку можно генерировать самим оборачиваемым объектом. Так что ли?
Re[4]: Полиморфные handle
От: Владислав Сомов http://forum.sukhoi.ru/forumdisplay.php?f=120
Дата: 06.12.05 13:44
Оценка:
Здравствуйте, Ignoramus, Вы писали:

I>Здравствуйте, Владислав Сомов, Вы писали:


ВС>>Здравствуйте, Владислав Сомов, Вы писали:


ВС>>>б) Хранить целое — объект-обертку, содержащую ссылку на объект.


ВС>>Это, по моему мнению, предпочтительней.


I>А как из обертки получить нужный тип объекта? (а не просто void* или ISuperBase* )


I>Я представил себе это так (чем-то напоминает паттерн visitor"):


I>Обертка имеет интерфейс в виде набора методов, возращающих все возможные типы, но все они кроме одного возвращают 0 для конкретной реализации обертки. Обертку можно генерировать самим оборачиваемым объектом. Так что ли?


Ну подойдем немного с другой стороны...

Клиент вызывает какую-то функцию, в которую передает хендл.
В итоге эта функция реализуется через функциональность класса, который представляет хендл (я правильно понимаю?).
Значит нам нужно убедиться, что это хендл именно ожидаемого класса. После этого операции преобразования безопасны.
Чтобы обезопасить себя, как программиста сервера (библиотеки с хендлами), нужно сосредоточить все операции над хендлами в одном месте.
Обертка полезна для реализации общей функциональности. Например, подсчет ссылок на хендлы, закрытие хендлов и прочее.

По сути, это именно то, о чем Вы сказали выше
Re: Полиморфные handle
От: MaximE Великобритания  
Дата: 06.12.05 14:15
Оценка:
On Tue, 06 Dec 2005 13:07:08 -0000, Ignoramus <18039@users.rsdn.ru> wrote:

> Для сопряжения С++ библиотеки и VB программы решил для представления объектов С++ использовать хендлы и процедурно-ориенторованный API (подобно WinAPI). Хендлы предполагаю хранить в ассоциативном массиве, в парах целое число — объект.

>
> Проблема в том, что объекты могут быть разных типов (классов). Варианты решения:
>
> 1) Поддерживать несколько таблиц хендлов — каждого типа отдельно, но тогда кол-во функций в API комбинаторно возрастает.
>
> 2) Различать тип объекта по хендлу. Например, разбить весь диапазон возможных значений хендлов на зарезервированные интервалы, и по интервалу определять тип, после чего делать соответствующий reinterpret_cast. Немного коряво и хаковато, зато типы могут быть совершенно независимы. (reinterpret_cast конечно хак, но система хендлов вообще — хак с точки зрения С++, а альтернативы ей я не вижу).
>
> 3) Наследовать все классы от одного интерфейса. Однако, если классы слишком разные, в этом обшем предке может вообще не оказаться полиморфных методов. Придется как-то даункастить, а этого хотелось бы избежать.
>
> Какие решения практикует all?

Слишком сложно ты напридумывал.

Делаем просто.

// api.h

// c-style api

struct handle;

handle* create_foo();
handle* create_bar();

long foo_fun(handle*);
long bar_fun(handle*);


// api.cpp
#include "api.h"

struct handle
{
     virtual ~handle() {}
};

struct foo : handle
{
     long fun();
};

struct bar : handle
{
     long fun();
};

handle* create_foo()
{
     return new (nothrow) foo;
}

long foo_fun(handle* h)
{
     if(foo* p = dynamic_cast<foo*>(h))
         return p->fun();
     else
         return E_BAD_HANDLE;
}


--
Maxim Yegorushkin
Posted via RSDN NNTP Server 2.0
Re[2]: Полиморфные handle
От: Владислав Сомов http://forum.sukhoi.ru/forumdisplay.php?f=120
Дата: 07.12.05 07:39
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>On Tue, 06 Dec 2005 13:07:08 -0000, Ignoramus <18039@users.rsdn.ru> wrote:


ME>Слишком сложно ты напридумывал.


ME>Делаем просто.


ME>
ME>// api.h

ME>// c-style api

ME>struct handle;

ME>handle* create_foo();
ME>handle* create_bar();

ME>long foo_fun(handle*);
ME>long bar_fun(handle*);
ME>


ME>
ME>// api.cpp
ME>#include "api.h"

ME>struct handle
ME>{
ME>     virtual ~handle() {}
ME>};

ME>struct foo : handle
ME>{
ME>     long fun();
ME>};

ME>struct bar : handle
ME>{
ME>     long fun();
ME>};

ME>handle* create_foo()
ME>{
ME>     return new (nothrow) foo;
ME>}

ME>long foo_fun(handle* h)
ME>{
ME>     if(foo* p = dynamic_cast<foo*>(h))
ME>         return p->fun();
ME>     else
ME>         return E_BAD_HANDLE;
ME>}
ME>


ME>--

ME>Maxim Yegorushkin

Боюсь, этого будет недостаточно. Вот пример:


#include <iostream>
#include <windows.h>

class CTestClassBase
{
public:
    CTestClassBase(){};
    virtual ~CTestClassBase(){};
    virtual void Test(int Member) = 0;
};

class CTestClass : 
    public CTestClassBase
{
public:
    CTestClass(){};
    ~CTestClass(){};
    void Test(int Member){m_Member = Member;};
private:
    int m_Member;
};

void Test()
{
    CTestClassBase * ptb1;
    CTestClassBase * ptb2;
    {
        CTestClass t;
        ptb1 = &t;
        // ptb1 = new CTestClass(); // Можно и так

        ptb2 = dynamic_cast<CTestClassBase *>(ptb1);
        ptb2->Test(100);

        // delete ptb1; // Можно и так
    }
    ptb2 = dynamic_cast<CTestClassBase *>(ptb1); // Вроде бы все хорошо
    ptb2->Test(200); // Упс, приехали :(

};

void main(void)
{
    Test();
}
Re[3]: Полиморфные handle
От: MaximE Великобритания  
Дата: 07.12.05 10:20
Оценка:
On Wed, 07 Dec 2005 07:39:23 -0000, Владислав Сомов <41483@users.rsdn.ru> wrote:

[]

> Боюсь, этого будет недостаточно. Вот пример:


Недостаточно для чего?

>
[]
>


Пример неудачен т.к. dynamic_cast<> не предназначен для проверки валидности указателей, использование его в качестве такого инструмента ошибочно.

Если необходимо обезопаситься от передачи невалидных указателей в API, что довольная редкая задача, придется хранить выданные указатели в какой-либо ст-ре данных и сверять их в вызове.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 2.0
Re[4]: Полиморфные handle
От: Владислав Сомов http://forum.sukhoi.ru/forumdisplay.php?f=120
Дата: 07.12.05 10:24
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Недостаточно для чего?


Для проверки валидности указателя.

ME>Пример неудачен т.к. dynamic_cast<> не предназначен для проверки валидности указателей, использование его в качестве такого инструмента ошибочно.


А такая проверка нужна.

ME>Если необходимо обезопаситься от передачи невалидных указателей в API, что довольная редкая задача, придется хранить выданные указатели в какой-либо ст-ре данных и сверять их в вызове.


О чем, собственно, и ведем речь
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.