Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как вызвать функцию не зная ее параметров, Что то из области научной фантастики? 
:(
    Опции темы
azesmcar
Дата 27.9.2005, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Здравствуйте...сам чую, то что я сейчас скажу попахивает маразмом, но все же спросить не помешает..

Есть класс CTclWrapperBase, в нем виртуальные функции...

Кто то другой (CChertEgoZnaetChto) наследует и добавляет свою (virtual void SomeFunction), вызывает мою функцию
RegisterTclFunction я делаю там всяческие преобразования..храню адрес его функции в каком нибудь массиве, это не важно...теперь вопрос

Возможно ли...чтобы я из своей функции класса TclWrapperBase зная что создан обьект типа CChertEgoZnaetChto вызвал SomeFunction зная только ее адрес, и параметры которые автор класса CChertEgoZnaetChto мне каким то образом передаст..

Вобщем точно что то из мира фантастики, но может хоть как то можно пройтись циклом по виртуальной таблице? В принципе проблем бы не было еслибы все функции написанные другими имели один и тот же формат, т.е. принимали одинаковые параметры, но как то не хочется их заставлять...проблема только с параметрами
Добавлено @ 14:33
Если хотя бы у кого нибудь есть документация о том как работает виртуальная таблица, где взять ее адрес и как с ней работать...тоже сойдет
PM   Вверх
Royan
Дата 28.9.2005, 14:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: нет
Всего: 15



Цитата
Если хотя бы у кого-нибудь есть документация о том как работает виртуальная таблица

Это зависит от компилятора. Например, в VС++ есть специальный указатель __vfptr. Его можно только похачить чтобы получить адрес виртуальной функции так не доберешься. Но эти хаки все очень не желательны, ибо можно всю таблицу виртуальных функций испортить.

Опять же возвращаясь в __vfptr, ее адрес как я понимаю (но может быть и ошибаюсь) можно выскоблить только путем асмовской вставки из ЦПП такое не сделать.


--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
Denn
Дата 28.9.2005, 15:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 143
Регистрация: 6.8.2005

Репутация: нет
Всего: 2



Насколько понимаю, именно на этапе компиляции неизвестно количество параметров. А что за функция SomeFunction()? У нее фиксированное или переменное количество параметров?
PM MAIL ICQ   Вверх
azesmcar
Дата 28.9.2005, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Это не именно одна функция, просто пример...кто-то наследует мой класс, добавляет свои виртуальные функции, вызывает мою функцию RegisterTclFunction. Теперь нужно из базового класса вызвать правильную функцию...например, я написал

Код


virtual void CChildClass::my_function()
{

//..........


}

CChildClass::CChildClass()
{
    RegisterTclFunction( my_function );
}



Если из TCL -а вызвать функцию my_function вызывается функция базового класса cmd_proc.

И cmd_proc должен решить какую именно виртуальную функцию своих потомков вызвать.
Проблемы бы не было еслиб все функции имели одинаковый прототип...но никто этого гарантировать не сможет...
PM   Вверх
DeadSoul
Дата 28.9.2005, 22:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1217
Регистрация: 25.9.2005
Где: Москва

Репутация: 2
Всего: 11



azesmcar, у тебя там есть иерархия классов? Судя по всему есть раз используешь виртуальные функции.
Почитай про паттерн Посетитель(Visitor)

P.S. К каким последствия приводит модификация таблицы виртуальных функций сказать не могу, но вряд ли к чему-то хорошему


--------------------
 Если Вы получили ответ на Ваш вопрос, то нажмите на "Вопрос решен". 

Бьем спамеров их же оружием. Пусть весь спам сыпется им
[email protected] 
PM   Вверх
azesmcar
Дата 30.9.2005, 11:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Почитаю, хотя подумал немного вижу другое решение, но для этого нужно кое что сделать...а вот как это сделать понятия не имею...

Как известно va_arg это макрос...аргумент ... тоже...

Если сделать так чтобы все функции принимали параметр va_list а потом уже хотя бы вызовом одного макроса или функции распределить все параметры функции по полочкам...например


Код

define Tcl_Param const char *pFmt, ...
virtual void test_func( Tcl_Param )
{
    int param1;
    char param2;
    GetTclParams( param1, param2 );
    //тут уже использование аргументов...
}


макрос GetTclParams должен сгенерировать код вроде
param1 = va_arg( ap_list, int );
param2 = va_arg( ap_list, char );

Формат параметров допустим у меня есть...

вопрос сводится к тому можно ли в С++ макросах писать циклы, или делать хоть какой то минимальный parsing? можно как то подумать над рекурсивными макросами но ANSI C++ их не поддерживает...могут возникнуть проблемы, не стоит..


PM   Вверх
Earnest
Дата 30.9.2005, 15:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Тогда уж не макрос, а шаблон(ы). Что-то вроде этого:

Код

template <class PAR1>
void GetParams(va_list args,PAR1& p1)
{
    p1 = va_arg(args,PAR1);
}

template <class PAR1,class PAR2>
void GetParams(va_list args,PAR1& p1,PAR2& p2)
{
    p1 = va_arg(args,PAR1);
    p2 = va_arg(args,PAR2);
}


Но все это весьма и весьма unsafe... Никто не проверит, что для вызова нужной функции в стек положили нужные аргументы. ИМХО, использовать такой подход можно только где-то в глубине кода, причем закладка параметров в стек и их извлечение должны осуществляться в рамках одного класса/модуля.

Кроме того, любая функция, вызываемая таким образом, нуждается в написании оболочки, которая будет извлекать для нее параметры из стека. Оно надо? Проще case написать по сигнатурам, как в MFC при диспетчеризации команд.

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




--------------------
...
PM   Вверх
Mad
Дата 30.9.2005, 17:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 7
Всего: 19



azesmcar
Цитата(azesmcar @ 30.9.2005, 10:21)
Формат параметров допустим у меня есть...

если у тебя есть формат параметров, то зачем так изгаляться ? smile

а если список параметров выберается в дочернем классе, то откуда твой родительский класс будет знать какие именно значения в эти параметры ложить ? smile


--------------------
user posted image
PM MAIL   Вверх
azesmcar
Дата 3.10.2005, 08:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата
а если список параметров выберается в дочернем классе, то откуда твой родительский класс будет знать какие именно значения в эти параметры ложить ? 


От вызова дочерним классом функции RegisterTclFunction...
Например так. RegisterTclFunction( interp, "test_function", "%s %d %c" );

Зарегистрирована Tcl функция которая принимает параметры типа %s %d %c всего три параметра..

будет осуществляться автоматическая проверка, при вводе менее трех параметров выдаваться на экран что то вроде help -a...и тому подобное...можно конечно чтобы все пользовательские функции принимали va_list но потом неудобно выковыривать из них параметры...

типа этого..

int param1 = va_arg( ap, int );
int param2 = va_arg( ap, int );
...
char param20 = va_arg( ap, char );

можно это как то автоматизировать макросом, или чем нибудь другим..вот и весь вопрос...


Цитата
Тогда уж не макрос, а шаблон(ы). Что-то вроде этого


Прелестно...ты представлешь приблизительно сколько страниц у меня будет занимать только обявления template -ов если вдруг юзеру заблагорассудиться (а ему наверняка заблагорассудится) написать функцию с приемом 20, 25 параметров...
Добавлено @ 08:03
Я думаю что то вроде этого должно быть на ассемблере


push param1
push param2

call function

разумееться это не код а описание...
PM   Вверх
Earnest
Дата 3.10.2005, 20:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



User'ов, которые пишут в C++ функции с 20 параметрами, нужно убивать в младенчестве.
Чтобы потом те, кто сопровождает их код, не чувствовали себя ассенизаторами. smile

Но даже и 20 шаблонов прописать - за пол-часа управишься. Не все ли тебе равно, сколько там страниц будет? Ровно так и поступают, кстати, такие библиотеки как boost в аналогичных случаях (конечно, не извлечение параметров из стека имеется в виду).

Хотя я лично ограничилась бы 5ю. Даже 3-мя. ИМХО, если у функции вдруг образовывается больше параметров, пора делать рефакторинг.
Юзер получит ошибку компиляции и задумается, на фига ему столько параметров. Не на Фортране пишет.

Но как я уже писала, это плохой способ, потому что небезопасный. Если нужно свести разнообразные события в одну точку вызова, способ один: упихать в какую-нибудь структуру типа Windows MSG. Или объявить что-то вроде интерфейса IData, и все передаваемые структуры данных от него наследовать.

Все-таки подумай: действительно ли тебе нужно все вызовы делать из одной точки? Может, тебе нужно что-то вроде делегатов?

Это сообщение отредактировал(а) Earnest - 3.10.2005, 20:45


--------------------
...
PM   Вверх
azesmcar
Дата 4.10.2005, 08:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата
Все-таки подумай: действительно ли тебе нужно все вызовы делать из одной точки? Может, тебе нужно что-то вроде делегатов?


Это Tcl Wrapper, если каждый будет писать вызовы для себя то кому же он тогда нужен этот wrapper?

Не знаю сколько юзеру захочеться написать параметров, но теоретически это возможно. и ограничивать возможности юзеров не очень то правильно...если теоретически ему захочется написать такую функцию он не сможет...

Можно конечно еще там что нибудь надумать..но лучше всего было бы автоматизировать этот процесс...т.е. или его надо автоматизировать или этого класса вообще не будет..
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0524 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.