![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| tilin |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
Класс А наследуется от IBase в котором есть метод Get(). В классе А этот метод переопределяется для возвращения конкретных значений. Нижеследующий пример конечно не работает, потому что возвращаемые типы Get() отличаются. А как вообще такое можно сделать.
|
|||
|
||||
| Alek86 |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1299 Регистрация: 30.1.2007 Где: Киев Репутация: 21 Всего: 25 |
tilin, что значит "не работает"?
что ты от него ожидаешь? допиши, в коде, желательно |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
||||
|
||||
| tilin |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
Не работает, значит не компилируется и ругается на то, что разные типы возвращаемых значений у IBase::Get и A::Get.
Чего хочется:
|
|||
|
||||
| Andrey44 |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1501 Регистрация: 4.12.2006 Где: На работе Репутация: 2 Всего: 26 |
А где же они будут одинаковыми? void!=T -------------------- ????? ??, ??????? ?????. |
|||
|
||||
| tilin |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
||||
|
||||
| Alek86 |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1299 Регистрация: 30.1.2007 Где: Киев Репутация: 21 Всего: 25 |
tilin, такое, как ты показал, невозможно
или boost::any или dynamic_cast |
|||
|
||||
| niXman |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 211 Регистрация: 4.7.2009 Репутация: 0 Всего: 0 |
Наверное это будет сложно для начинающего. Напиши микро-аналог variant. Что-то типа этого:
Это сообщение отредактировал(а) niXman - 27.10.2009, 15:03 --------------------
if ( !c++ ) { *power--; this->wussiness += 10;} |
|||
|
||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
tilin, интересно, а как ты этим пользоваться собирался? Вот например, кусок кода не знает ничего о типе Type, для которого был в другом месте кода создан экземляр класса A<Type>... Так вот, что будет делать твой кусок кода с тем, что вернет A<Type>::Get? Я уж не говорю о том, что это даже теоретически скомпилировать нельзя.
|
|||
|
||||
| tilin |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
Ну кратко так: A<type> создается в одном месте кода, затем помещается в массив. С массивом работает код, который может например определенным образом сортировать элементы массива, добавлять, удалять и т.д. А где-то из этого массива извлекается значение A<type> и используется. Смысл в том, что тот кто помещает в массив и тот кто извлекает из массива имеют нужную информацию о типах. А массив может содержать конечно только элементы одного типа, отсюда и наследование от единого интерфейса. |
|||
|
||||
| Alek86 |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1299 Регистрация: 30.1.2007 Где: Киев Репутация: 21 Всего: 25 |
тогда dynamic_cast а если ну совсем уверен, то даже static_cast вниз по иерархии Это сообщение отредактировал(а) Alek86 - 27.10.2009, 15:40 |
|||
|
||||
| tilin |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
При получении значения static_cast до требуемого типа вполне подходит. И как я понял других вариантов, кроме как возвращать Variant, нет. Буду делать так. Спасибо. Меня только смущает, что в этом случае требуется создавать временный объект Variant в функции Get(). Это сообщение отредактировал(а) tilin - 27.10.2009, 16:17 |
|||
|
||||
| niXman |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 211 Регистрация: 4.7.2009 Репутация: 0 Всего: 0 |
Создай локальный в твоем классе, инициализируй его в функции Get(), и возвращай на него ссылку. --------------------
if ( !c++ ) { *power--; this->wussiness += 10;} |
|||
|
||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 41 Всего: 154 |
можно использовать паттерн - visitor
|
|||
|
||||
| tilin |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
Так и сделал. Только не в Get, а сразу при создании объекта. А Get возвращает Вариант. |
|||
|
||||
| tilin |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
А в этом случае не придется для каждого типа добавлять новый оператор в IVisitor? Если да, то не подходит. Это сообщение отредактировал(а) tilin - 27.10.2009, 23:25 |
|||
|
||||
| Lazin |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 41 Всего: 154 |
если они однотипные, то их можно сгенирировать с помощью шаблона если ты будешь использовать variant, то у тебя в коде будет что-то вроде -
visitor - это то-же самое, только принятие решения, о том, как обрабатывать значение ложится на компилятор (перегрузка ф-ии) и в любом случае, тебе придется написать код для разных типов(либо использовать шаблон, для нескольких похожих типов) |
||||
|
|||||
| tilin |
|
||||||||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
Типы могут быть любые. Вариант у меня выглядит вот так:
В классе есть
В коде значение получается например так:
|
||||||||
|
|||||||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 41 Всего: 154 |
и как-же ты с ними работаешь потом, если не секрет? |
|||
|
||||
| tilin |
|
||||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
Вопрос не совсем понял, но например в варианте с int так:
|
||||
|
|||||
| Lazin |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 41 Всего: 154 |
во первых, здесь нужно явное приведение типа (static_cast), во вторых, если в v[0] не int - оператор приведения типа бросит исключение, мне интересно, что ты будешь делать, если у тебя в одном контейнере значения разных типов, как в твоем первом примере?
|
||||||
|
|||||||
| tilin |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
Вот пример - код рабочий.
|
|||
|
||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 41 Всего: 154 |
и бесполезный приходи, когда попробуешь написать реальный код, использующий этот класс, вопросы сразу возникнут, я гарантирую это |
|||
|
||||
| tilin |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
Вообще заморочки с Вариантом требовались для вполне реального кода, в продолжение поста Получение типа параметра функции. А нужно это все для того чтобы на автомате создавать объекты хранящие вызов функции вместе с параметрами и возвращаемым значением. Вот для получения возвращаемого значения из объекта хранящего вызов и потребовалось представить его Вариантом. Потому что такие объекты наследуются от абстрактного интерфейса и помещаются в вектор. Все прекрасно работает. |
|||
|
||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 41 Всего: 154 |
пока ты знаешь тип возвращаемого значения просто у тебя нет способа узнать тип значение, хранящегося в Variant-e, я уже несколько постов пытаюсь на это намекнуть
вообще, лень вникать, sry просто, если у тебя не возникает необходимости определять тип значения, хранящегося в Variant-е, значит вероятно, тебе вообще не нужен Variant, ты просто усложнил архитектуру приложения |
|||
|
||||
| tilin |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
Нет, код который получает результат тип знает конечно. Как этот код выбирает объекты из контейнера - это другой вопрос. Но факт, что все объекты в контейнере должны иметь один тип, отсюда и наследование интерфейса, а из наличие в интерфейсе одного виртуального Get() на все наследуемые типы требует, чтобы Get() возвращал Вариант, который неявно преобразовывается к требуемому типу.
|
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
если тип объекта известен и помощь компилятора не требуется, то хранить объект можно и как void * как раз от такого как происходит взаимодействие с элементом контейнера и зависит какой интерфейс должен поддерживать объект. как я понимаю у Вас тип зависит от индекса, тогда если контейнер условно находится в библиотеке которая ничего не знает о типах, и предоставляет просто место для хранения, то тут как раз хранение по void* и каждый клиент имеет интерфейс по получению "готовых" объектов. если же нужно хранить разношерстные элементы как одну структуру и все типы статически известные, то посмотрите например библиотечку boost::fusion в частности : http://www.boost.org/doc/libs/1_40_0/libs/...ner/vector.html В общем предположить что Вам требуется можно в разных вариантах и для каждого варианта нужен свой подход, поэтому, чтоб не гадать , было бы лучше если бы Вы полноценно осветили бы свое задание. |
|||
|
||||
| tilin |
|
||||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
Абсолютно не зависит. Объекты в массив добавляются в произвольной последовательности. В первом варианте Get() возвращал именно void*, потом клиент делал static_cast до нужного типа. Но мне хотелось, чтобы вместо
было
Конечно использовать динамическое приведение типов вместо статического не есть Гут. И я еще подумаю, какой из них выбрать. |
||||
|
|||||
| mes |
|
||||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
так тип объекта с чем то связан или программист сам должен помнить под какой индекс что он добавил ?!
имхо, приведенной в этом топике информации недостаточно для совета. |
||||
|
|||||
| tilin |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
Общая задача выглядит так:
Требовалось реализовать объект, хранящий указатель на объект некого класса, указатель на метод класса, параметры вызова и возвращаемое значение. Такие объекты формируются вместе с параметрами, помещаются в список вместе с метаданными. Список преобразовывается. Некоторые элементы перемещаются в начало, некоторые в конец и т.д. Затем по определенным условиям вызывается метод Call объектов. Возвращаемое значение сохраняется в объекте. Затем по метаданным ищется объект в списке и код получает результат вызова (точно зная его тип конечно). |
|||
|
||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
tilin, правильно ли я тебя понял, тебе нужно создавать "задачу", которая в большинстве случаев выглядит как вызов: result = object->method(data)?
Если result всегда одного типа, то рекомендую обратить внимание на boost::bind (для создания "задач") и boost::function (для хранения "задач" в контейнере). Если разных типов, то еще и на boost::any. например, у тебя есть метод int A::method(double x). Ты хочешь его поставить в очередь задач a->method(1.0), тогда boost::bind(&A::method, a, 1.0) создаст тебе объект, который можно вызывать так: o(). Чтобы этот объект чему-нибудь присвоить (пока нет auto из c++0x) можно использовать или шаблоны или boost::function: boost::function<int()> f = boost::bind(&A::method, a, 1.0). Теперь появился функциональный объект f, который можно вызвать так: f(). А вот это уже можно хранить в контейнере (для случая с any):
Это сообщение отредактировал(а) bsa - 28.10.2009, 17:43 |
|||
|
||||
| tilin |
|
||||||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
Да надо создавать что-то типа задачи, которая хранит объект, метод, параметры вызова и возвращаемое значение. Однако результ может быть совершенно разного типа. В сторону boost-а я уже начал смотреть, но пока с целью ознакомления только лишь. Выложу свое решение, поправьте, если что не то сделал. Списки типов из библиотеки Loki. В Loki NullType.h заменено:
Основная реализация такая:
Макросы только для удобства записи. Пример использования. Func6 для примера без использования макроса SETTYPES:
|
||||||
|
|||||||
| bsa |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
tilin, я тебе дал готовое решение, которое в разы проще и надежней твоего - используй его!
Забыл написать, как добавлять задачи. Допустим, есть менеджер задач, у которого есть метод добавления, объявленный так:
Кстати, начиная с версии 1.35 в boost уже есть менеджер задач! Вот только находится он в неочевидном месте и еще менее очевидно называется. Это boost::asio::io_service. Чтобы с ним работать нужно знать всего два метода: io_service::post() (постановка задачи на асинхронное исполнение), и io_service::run() (выполнение всех задач, пока они есть в очереди; может быть вызван одновременно в нескольких потоках, что приведет к параллельному исполнению задач). |
||||||
|
|||||||
| Lazin |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 41 Всего: 154 |
а еще - функциональней, благодаря полиморфному поведению boost::function, в качестве задач можно использовать не толко ф-ии, но и методы и функторы, твой пример можно переписать вот так:
Добавлено через 4 минуты и 51 секунду кстати, если нет желания использовать boost::asio::io_service, то можно просто сделать не шаблонный класс - наследник Task, у котрого был-бы определен виртуальный метод result, complete и operator() и работать с объектами Task - полиморфно
Это сообщение отредактировал(а) Lazin - 29.10.2009, 16:47 |
||||||
|
|||||||
| tilin |
|
||||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
Все понял.
Честно, я понятия не имел, что если сделать вот так
а потом вот так
То в bind будут автоматически определены типы. Я в шоке. Век живи - век учись ) |
||||
|
|||||
| bsa |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
Решил свой аналог boost::bind сделать? |
||||||
|
|||||||
| tilin |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
Просто очень хочется разобраться как делаются такие вещи Вот что получяется. Я в правильном направлении?
|
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
весь код не смотрел, но судя по этой строке : имхо Вы держите путь в сторону. Это сообщение отредактировал(а) mes - 30.10.2009, 14:27 |
|||
|
||||
| tilin |
|
||||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
А вот если добавить сохранение результата в виде Варианта, тогда при получении значения руками преобразования типов делать не надо:
Только в моем варианте dynamic_cast пользуется, поэтому наверное стоит поучиться у boost::any ) В общем вот так получается
|
||||
|
|||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |