Re[18]: Адрес метода
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.07.01 20:51
Оценка:
Здравствуйте Alex Fedotov, вы писали:

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


VD>>Вот Александр Шаргин дал красивую идею как убрать asm пир копировании указателя на функцию. Может поможете убрать оставшийся asm?


AF>А зачем? Все равно это как было шаманством, так шаманством и останется, полагающимся на реализацию конкретного компилятора.


Думаю, другие компиляторы устроены также. К тому же они мне по барабану. Взяв за основную библиотеку ATL вряд ли будишь задумываться о переносимости. Да, и проблем особых нет! Надо будет, сделаем #if... для нужного компилятора.

AF>Нет, нет и еще раз нет, если мы говорим о языке C++.


Я скорее всего говорю о диалекте этого языка от MS и его реализации в VC. Она пока от стандарта отличается.

AF>В момени инизиализации указателя

AF>CPtr ptr = CC::B;

AF>известен только класс, который будет вызываться, а экземпляр класса, может появиться много позже.


Эта и есть никчемная реализация которая меня не устраивает. Да, и плевать мне на то, что Страуструп и орлы из команды VC не додумались до такой простой идеи.
Мне хочется работать легко и писать красивый код! Я уже продемонстрировал, работоспособность такого указателя.


AF>Хорошо известный пример — message maps в MFC, которые хранят указатели на члены класса. А объект появляется гораздо позже, более того, их может быть несколько.


Но мне-то это извращение НЕ НУЖНО! Мне больше нравится реализация в ATL. Она значительно более гибка! Кстати, в ATL есть несколько мест, которые являются извращениями ни чуть не меньшими чем мое... ну и почему все используют ATL и не говорят, что это "не переносимо, шаманство, ...", а? А в Delphi половина базового класса TObject на asm-е написано... Попробуйте сказать Дельфинарию слова про шаманство! :)

AF>Твой же UniversalFuncPtr -- скорее аналог интерфейса, чем указателя на метод класса. Кстати, в реальной жизни, я пользуюсь именно интерфейсами, а не указателями на члены класса.


Он не скорее, а совершенно точно аналогичен указателю на функцию экземпляра в Delphi, Делегату в .Net и т.п. А еще он аналогичен call-back-функции получающей хэндлер, а на интерфейс он совсем не похож (Интерфейс – это указатель на vtbl фиксированного вида). Интерфейсы и я использую, но использовать их для реализации событий (внутри своего кода) — это большой геморрой (Уж с ними мы натрахались вдоволь, в Ax-ах и COM я то точно кое-что понимаю). К тому же у них есть один недостаток – в одном классе, интерфейс нельзя реализовать боле одного раза. Тат же ATL для обхода этого использует примочки в виде базовых классов XxxImpl. Конечно, можно сделать код на базе сообщений Windows, но хочется как то поэлегантней.

AF>Ну, программисты на некоторых других языках (не будем показывать пальцем), считают, что множественное наследование является кривым местом, давайте теперь его исправлять.


Множественное наследование мне нравится, и отказываться от него не хочется (очень жаль, что в .Net на нем поставлен крест). Особенно оно эффективно в сочетании с шаблонами (коих в .Net тоже не наблюдается, но в будущем обещают)...
Раньше я даже не мог понять, почему все новомодные языки стремятся его избежать, а теперь начинаю понимать... Хотя, похоже, всему виной непродуманность, а не реальные проблемы с множественным наследованием.

AF>Я не считаю вызовы функций-членов класса кривыми и я понимаю, почему они реализованы именно так, а не иначе.


А я считаю, что указатели на функции в старом добром C были мощным и удобным инструментом, а указатели на функции-члены в C++ стали совершенно бесполезным хламом. Любое использование этой фичи (которое может прийти мне на ум) можно заменить более изящными средствами (теми же интерфейсами, шаблонами...), а там где это действительно нужно они просто непригодны, из-за "ПРЯПОЙ" реализации. Мне нужно вызывать метод у любого объекта по некоторой ссылке. Именно это и недает мен данная реализация.
MS пытается продать делегаты как свое открытие, тогда как реально их использовали еще на C. И только по вине Страуструпа в C++ не появилось такого же удобного, гибкого и мощного средства как "указатели на функции экземпляра объекта".

PS

Любой язык, претендующий на звание "живого" должен развиваться. Многое, что мы сейчас видим C++ это плод обобщения использования ОО-методов в том самом C. На C чтобы с эмулировать объектную ориентацию приходилось изгаляться не хуже моего. Ну, и что? C++ вобрал в себя все, что мог дать C и привнес несколько фичь которые позволили (более менее) программировать на этом языке как на ОО. Так вот если C++ не хочет уступить место языкам без множественного наследования и других "излишеств" (таким как C# или гы-гы VB.Net) он должен вбирать правильные идеи, а начинаются такие идеи с вот таких извращенческих шаманств. :).

Короче, раньше бы я плюнул, а теперь обязательно это дело на чистых плюсах перепишу. :)
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Адрес метода
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.07.01 21:07
Оценка:
Здравствуйте Аноним, вы писали:

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


V>>К куче существующих окон необходимо заменить WindowProc.

V>>Первое, что пришло в голову, создать класс CMyWnd,
V>>содержащий метод MyWndowProc и атрибут OldWindwProc.
V>>Одна универсальная функция неэффективна, т.к. единственное
V>>различие для вызовов из разных окон это значение hWnd?
V>>а по нему искать каждый раз OldWindwProc не хочется.

V>>Вопрос 1: Как заполучить адрес метода из экземпляра класса для SetWindowLong?

V>>Вопрос 2: Как иначе организовать множество функций различающихся только
V>> значением атрибута OldWindwProc.

А>1. В MFC эта задача решена через глобальную таблицу экземпляров классов окон.

А>2. В ATL более красиво, без всяких-там SetWindowLong, — через thunk:
А>поищи в сорцах ATL (atlwin.h) все, что связанно с
А>struct _WndProcThunk
А>{
А> DWORD m_mov; // mov dword ptr [esp+0x4], pThis (esp+0x4 is hWnd)
А> DWORD m_this; //
А> BYTE m_jmp; // jmp WndProc
А> DWORD m_relproc; // relative jmp
А>};


Господа! Хочется задать вопрос!

Так, такие /\/\/\/\ вещи это красИииво или извращЩщщение?! :)

И что лучше без извращений, но с глобальным Мапом, или с извращениями, но коротко и эффективно?


Не стесняйтесь. Высказывайтесь. Интересно любое мнение.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: Адрес метода
От: Alexander Shargin Россия RSDN.ru
Дата: 20.07.01 16:14
Оценка:
Здравствуйте VladD2, вы писали:

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



VD>Ну, а как на счет замены для вызова функции на asm-е? Я как то пробовал заменить его на вызов в стиле C-декл. (в смысле, глобальной функцией описанной как стандартная сишная ф-я), но что-то у меня не вышло. :( На asm-е получилось проще. :)



Ну, чувствую я, что меня опять назовут извращенцем. :)

На самом деле, чтобы вызвать функцию, достаточно какого-нибудь класса, у которого указатель на функцию "весит" 4 байта. Идеальный кандидат — сам CUniversalFuncPtr. Используя эту идею, вместо

int iRetVal;
__asm
{
// Эмулируем thiscall
mov ecx, UniversalFuncPtr.pThis;
mov eax, UniversalFuncPtr.pF;

//push i ; // закладываем значение параметра
call eax // ecx.f1(i);
mov iRetVal, eax
}
return iRetVal;


можно написать:

CUniversalFuncPtr *ptr;
int (CUniversalFuncPtr::*pfn)();

ptr = (CUniversalFuncPtr *)UniversalFuncPtr.pThis;
(void*&)pfn = UniversalFuncPtr.pF;

return (ptr->*pfn)();



С уважением,
Александр
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
Re[18]: Адрес метода
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.07.01 17:20
Оценка:
Здравствуйте Alexander Shargin, вы писали:

AS>Ну, чувствую я, что меня опять назовут извращенцем. :)


Не присваивайте чужой славы! Извращенцем называли меня. :)

AS>На самом деле, чтобы вызвать функцию, достаточно какого-нибудь класса, у которого указатель на функцию "весит" 4 байта.


Собственно я так с самого начала думал, но толи не все так просто, толи я лоханулся при создании кода...

AS>Идеальный кандидат — сам CUniversalFuncPtr. Используя эту идею, вместо


AS> int iRetVal;

AS> __asm
AS> {
AS> // Эмулируем thiscall
AS> mov ecx, UniversalFuncPtr.pThis;
AS> mov eax, UniversalFuncPtr.pF;
AS>
AS> //push i ; // закладываем значение параметра
AS> call eax // ecx.f1(i);
AS> mov iRetVal, eax
AS> }
AS> return iRetVal;


AS>можно написать:


AS> CUniversalFuncPtr *ptr;

AS> int (CUniversalFuncPtr::*pfn)();

AS> ptr = (CUniversalFuncPtr *)UniversalFuncPtr.pThis;

AS> (void*&)pfn = UniversalFuncPtr.pF;

AS> return (ptr->*pfn)();


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

А можно ли передавать тип указателя на функцию в качестве параметра шаблона?

PS

Я давно мечтал о человеческой реализации фичи которую теперь называют делегатами.

В любом случае спасибо! И последний вопрос может, создадим статейку на эту тему. Ведь за последнее время эта тема собрало самую большую аудиторию.

К ALL: Если считаете, что такая статья нужна, шлите сюда свои постинги с подтверждением, а так же предложения.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[19]: Адрес метода
От: Alexander Shargin Россия RSDN.ru
Дата: 20.07.01 17:39
Оценка:
Здравствуйте VladD2, вы писали:

AS>>На самом деле, чтобы вызвать функцию, достаточно какого-нибудь класса, у которого указатель на функцию "весит" 4 байта.

VD>Собственно я так с самого начала думал, но толи не все так просто, толи я лоханулся при создании кода...

Не знаю, там единственная тонкость — приведение (void*&)pfn.


AS>>Идеальный кандидат — сам CUniversalFuncPtr. Используя эту идею, вместо

<skip>

AS>>можно написать:

<skip>

VD>Не очень красиво получается. При таком подходе надо каждый раз создавать новый базовый класс. Надо подумать на счет чего-то более универсальной реализации. Может быть что-то на тех же шаблонах?


Про шаблоны я уже сам занёс руку тебе написать, но вовремя остановился. Дело в том, что, раз уж мы заговорили о делегатах, нам нужна возможность "на лету" заменять указатель на функцию одного объекта указателем на функцию совсем другого. Поэтому придётся оставить всё, как есть.

А новые классы создавать не надо — зачем? Код, который я привёл, эквивалентен твоему ассемблеру: если ты правильно задал this и адрес функции, он будет работать для самых различных объектов... Он ведь просто помещает ptr в ecx и делает call pfn... Хотя это, конечно, извращение... ;)


Александр
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
Re[20]: Адрес метода
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.07.01 19:47
Оценка:
Здравствуйте Alexander Shargin, вы писали:

Будет время попробую по-колдовать еще разок. Может выйдет что путное и красивое.

PS

Тут, вот, некоторые говорять извраЩщщение... а некоторые приводят примеры из ATL-ного сабкласинга и говорят красота. Так что — то что для одного изврат, для другого красота. ;)

Еще раз спасибо!
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[15]: Адрес метода
От: IAZ http://iaz.simb.ru
Дата: 22.07.01 17:13
Оценка:
Здравствуйте VladD2, вы писали:

VD>Так всеже можно тоже самое сделать на сях без asm-а?


Смотря что вы подразумеваете под "темже самым".
А по другому конечно можно :)

структура классов CA, CB, CC таже, повторять нет смысла.

template<class R, class T> class mem_fun_t2
{
typedef R (T::*MFPtr)();
MFPtr pF; // указатель на функцию класса T
public:
explicit mem_fun_t2(MFPtr p) : pF(p) {}
R operator() (T* p) { return (p->*pF)(); } // вызов фунции из конкретного объекта класса T
};

int main(int argc, char* argv[])
{
typedef int (CC::*CPtr)();
CPtr pF= CC::B;
mem_fun_t2<int, CC> fB(pF); // в объекте fB теперь находиться указатель на CC::B

CC c;
printf("mem_fun_t2 returns %d", fB(&c)); // вызов c.B();
printf("c.B() returns %d", (c.*pF)());
return 0;
}

Между прочим, это не я придумал, оригинальный класс mem_fun_t находиться
в файле "functional" из STL.
Можно продолжить идею создания "универсального" указателя на функцию и, в частности, callback. Например, так:

// mem_fun так-же описана в "functional"
template<class R, class T> mem_fun_t2<R,T> mem_fun2(R (T::*f)())
{
return mem_fun_t2<R,T>(f); // всего лишь создаем и возвращаем объект mem_fun_t2
}

// вместо этой функции может быть и класс
template<class R, class Function> R f(Function F)
{
//...
CC c;
R m=F(&c); // F нет в классе СС!
//...
return m;
}

int f2(CC* pC)
{
// все что угодно
//...
return 4;
}

int main(int argc, char* argv[])
{
int m=f<int>(mem_fun2(CC::B)); // вызов CC::B
m=f<int>(f2); // вызов f2
return 0;
}
Кто ищет то всегда найдет!
Re[19]: Адрес метода
От: IAZ http://iaz.simb.ru
Дата: 22.07.01 18:10
Оценка:
Здравствуйте VladD2, вы писали:

VD>Но мне-то это извращение НЕ НУЖНО! Мне больше нравится реализация в ATL. Она значительно более гибка! Кстати, в ATL есть несколько мест, которые являются извращениями ни чуть не меньшими чем мое... ну и почему все используют ATL и не говорят, что это "не переносимо, шаманство, ...", а? А в Delphi половина базового класса TObject на asm-е написано... Попробуйте сказать Дельфинарию слова про шаманство! :)


Подобные вещи (использование asm там где можно и без него обойтись) перестауют быдь шаманством только тогда, когда они хорошо протестированы на всех доступных системах и окружениях. И даже тогда остается покрайне мере несколько ситуаций когда они (реализации) будут кардинально не верны.


AF>>Я не считаю вызовы функций-членов класса кривыми и я понимаю, почему они реализованы именно так, а не иначе.


VD>А я считаю, что указатели на функции в старом добром C были мощным и удобным инструментом, а указатели на функции-члены в C++ стали совершенно бесполезным хламом. Любое использование этой фичи (которое может прийти мне на ум) можно заменить более изящными средствами (теми же интерфейсами, шаблонами...), а там где это действительно нужно они просто непригодны, из-за "ПРЯПОЙ" реализации. Мне нужно вызывать метод у любого объекта по некоторой ссылке. Именно это и недает мен данная реализация.

VD>MS пытается продать делегаты как свое открытие, тогда как реально их использовали еще на C. И только по вине Страуструпа в C++ не появилось такого же удобного, гибкого и мощного средства как "указатели на функции экземпляра объекта".

Средство "указатели на функции экземпляра объекта" подразумевает две вещи:
1. указатель на объект
2. указатель на функцию в _этом_ объекте
Все это присутствует в С++
Избавивщись от первого мы избавляемся от самого объекта. Так может программировать тогда С? Или использовать глобальные функции, или статические. А может быть по-другому спроектировать программу. Вот ты критикуешь С++ и хвалишь ATL (читай MS) за то что они исправляют "ошибки" Страуструпа. Интерестно какова сложность проектирования C++ и ATL (MFS & etс.)? Где и кем используется С++ и ATL? В конце концов ATL это всего лишь библиотека которую написали как смогли, на том _подмножестве_ C++ которое знали эти программисты и которое поддерживает этот компилятор.

PS: нет такого языка, который бы всем нравился и всех удовлетворял

С уважением, IAZ.
Кто ищет то всегда найдет!
Re[14]: Адрес метода
От: IAZ http://iaz.simb.ru
Дата: 22.07.01 18:54
Оценка:
Здравствуйте VladD2, вы писали:

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


AF>>Как компилятор узнает, что p указывает на функцию из класса B, а не из класса A?


VD>Если функция не виртуальная, то ее адрес всегда фиксирован. Адресс функции — это всеголишь адресс ее первой инструкции.


VD>А если так, то смешение может относиться только к сдвизке this (о чем собственно и коворил Шаргин). Структура всех классов известна компилятору и он может добавлять или вычитать смещение сам без доп информации. Так вот, мне и непонятно почему такие плевые операции компилятор не может расчитать сам?


Почему не может? В определенных случаях он даже может виртуальную функцию сделать inline. Но в общем случае пологаться на это нельзя.
Кто ищет то всегда найдет!
Re[15]: Адрес метода
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.07.01 19:10
Оценка:
Здравствуйте IAZ, вы писали:


IAZ>Почему не может? В определенных случаях он даже может виртуальную функцию сделать inline. Но в общем случае пологаться на это нельзя.


Гы-гы. ("может"... "пологаться на это нельзя")

PS
Вы или не разобрались в вопросе, или не хотите меня пнять.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[19]: Адрес метода
От: IAZ http://iaz.simb.ru
Дата: 22.07.01 19:12
Оценка:
Здравствуйте VladD2, вы писали:

VD>В любом случае спасибо! И последний вопрос может, создадим статейку на эту тему. Ведь за последнее время эта тема собрало самую большую аудиторию.


VD>К ALL: Если считаете, что такая статья нужна, шлите сюда свои постинги с подтверждением, а так же предложения.


Сомневаюсь, что такая статья необходима — зачем переливать из пустого в порожнего: так нельзя попробуйте по другому. Это тянет не больше чем на маленький FAQ.
А если все таки написать статью, то неизвестно как она повлияет на неокрепшую психику начинающего программиста. Из-за отсутвия опыта и знаний он может это использовать не поназначению. А чтобы охватить все аспекты этой проблемы одной статьи мало.

С уважением, IAZ.
Кто ищет то всегда найдет!
Re[16]: Адрес метода
От: IAZ http://iaz.simb.ru
Дата: 22.07.01 19:36
Оценка:
Здравствуйте VladD2, вы писали:

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



IAZ>>Почему не может? В определенных случаях он даже может виртуальную функцию сделать inline. Но в общем случае пологаться на это нельзя.


VD>Гы-гы. ("может"... "пологаться на это нельзя")


VD>PS

VD>Вы или не разобрались в вопросе, или не хотите меня пнять.

Очепяток тут хватает, я бы не стал на этом заострять внимание :)

Вопрос был в следующем: присвоить указателю на глобальную функцию указатель на функцию-член. Стандарт это не позваляет. Во многих случаях во время исполнения не происходит добавления этого смещения — добавляется при компиляции. Так что реально такая функция становиться самой обычной (как глобальная). Но еще раз сошлюсь на стандарт: он не позволит обращаться с таким указателем как с обычным. Но asm'е это можно успешно преодалеть, только работать будет не всегда.
Кто ищет то всегда найдет!
Re[20]: Адрес метода
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.07.01 21:22
Оценка:
Здравствуйте IAZ, вы писали:

IAZ>Подобные вещи (использование asm там где можно и без него обойтись) перестауют быдь шаманством только тогда, когда они хорошо протестированы на всех доступных системах и окружениях.


Ну, "когда они хорошо протестированы на всех доступных системах", это Вы хватили. :)
Кто же даст на свою систему залезть, да и вся жизнь на это уйдет. ;)

Вполне достаточно логического обоснования, ну и может тестирования на компиляторах которые необходимо поддерживать. Для меня – это, пока, VC 6 и VC 7.

IAZ> И даже тогда остается покрайне мере несколько ситуаций когда они (реализации) будут кардинально не верны.


Т.е. если есть asm-вставка, то обязательно когда ни будь грохнет? А как же половина MS CRT — написанная на asc-е? И куски из ATL?

Дело в том, что если есть человеческий метод решения на основном языке, то выпендриваться на asm-е, просто, нет необходимости (если конечно не нужно оптимизировать производительность). Но, не всегда это возможно. Иногда это реальная необходимость (недоработки языка или компилятора), а иногда просто в голову не приходит. :) Вот Шаргин тут давичи показал пример использования шаблона-объединения. Понятно, что вещь стандартная и предусмотренная языком, но вот не пришла она в голову, а на асм-е я там совсем примитивную вещь делал – 4-е байта копировал. Неужели от этого могут быть какие-то проблемы? Да и спецификация thiscall-а полностью описана. Так что проблема здесь может возникнуть, только если первые 4-е байта указателя на функцию класса будут содержать что ни будь отличное от указателя на функцию. В VC такое невозможно, в других компиляторах... возможно конечно, но мало вераятно. Будет возникать проблема с переносимостью разобрались бы с конкретным компилятором и... Ну, а asm здесь вообще не причем напишите такой код хоть на C, хоть на C++, хоть на VB, ровным счетом ни чего не изменится. Здесь налицо зависимость от компилятора.

IAZ>Средство "указатели на функции экземпляра объекта" подразумевает две вещи:

IAZ>1. указатель на объект
IAZ>2. указатель на функцию в _этом_ объекте

Ага.

IAZ>Все это присутствует в С++


Ага. Но по отдельности. И указатель на функцию одного класса нельзя нормальными средствами преобразовать в указатель на функцию другого объекта. Вот и приходится выходить из положения. Можно конечно воспользоваться указателями на интерфейс (как мне тут советовали), но я уже так ... (почему это неудобно можно почесть из моего ответа тому кто советовал).

IAZ>Избавивщись от первого мы избавляемся от самого объекта. Так может программировать тогда С? Или использовать глобальные функции, или статические.


Причем здесь C и глобальные функции я не знаю, но именно "от первого" и избавился СтраусТруп при создании своих указателей. Может он подразумевал, что указатели на функции разных классов можно будет попросту приводить друг к другу? Я не знаю но реалии жизни, в лице VC, плюют на все предпложения...

IAZ>А может быть по-другому спроектировать программу.


Можно конечно (можно нагородить кучу кода для создания простого алгоритма), а можно и язык по-другому... или небольшой классик/шаблончик нарисовать...

IAZ> Вот ты критикуешь С++ и хвалишь ATL (читай MS) за то что они исправляют "ошибки" Страуструпа.


Страуструпа, да пожалуй, я критикую. Пару тройку правильных решений он не учел.
А "хвалишь ATL" – боже упаси. Я просто заметил, что когда гуру из MS пишут нетривиальный код (иногда использующий asm) для того чтобы потом работать легко и просто, то их называют молодцами, а код называют "красивым". Ну, а если аналогичные действию делают другие, то сразу начинается ханжество (заранее извините, если я кого оскорбил этим словом). Еще раз повторюсь – я с удовольствием переписал бы этот код на чистом C++, но пока красивого законченного решения у меня нет. :(

IAZ> Интерестно какова сложность проектирования C++ и ATL (MFS & etс.)? Где и кем используется С++ и ATL? В конце концов ATL это всего лишь библиотека которую написали как смогли, на том _подмножестве_ C++ которое знали эти программисты и которое поддерживает этот компилятор.


Ннн-да, думаю, что программисты эти были одними из лучших в мире. По крайней мере, нас с Вами они, похоже, превосходят. Так, что можно не сомневаться, что C++ они знают в совершенстве. И не в реализации дело. В VC реализовано (я говорю только о нашей проблеме) то, что было описано в стандарте. Т.е. указатель на некоторую функцию КОНКРЕТНОГО класса! А мне нужен указатель на функцию ЭКЗЕМПЛЯРА объекта. Улавливаете разницу? Так что здесь налицо неграмотное планирование! Планирование элемента языка программирования. Как я уже говорил эту фичу (глубоко наплевав на Дельфи) MS продала за новую идею, назвала ее делегатами, и попыталась встроить ее в Яву. :)

И почему Вы думаете, что "ATL это всего лишь библиотека которую НАПИСАЛИ КАК СМОГЛИ", а C++ это незыблемая вещь которую написали бессмертные гении? Страуструп совсем непохож на Моцарта, да и у последнего не все произведения становились бессмертными. Лажался Страуструп (при создании этого языка) не мало. Так что мы всего лишь замазываем за ним дырки. Не, я понимаю, что многих идей просто не было в то время, например сборки мусора, но указатели на функции он попытался перенести в объектно-ориентированную среду, но … но облажался. Получилась никчемная реализация (из хорошей идеи).

IAZ>PS: нет такого языка, который бы всем нравился и всех удовлетворял


Полностью согласен, но большинство вещей в C++ меня устраивает (недоработок много, но большинство из них можно залатать средствами самого языка). А так... значит если я встретил проблему, то лапки к верху и пошел делать так как получается? Не-ааа, это не для меня. Криво — поправим. Скрипит — подмажем...

А, за Ваш совет (в другом постинге) спасибо. Правда, пока я не разобрался можно ли из него почерпнуть чего интересного, но все равно спасибо!

Будет время, попробую по колдовать. Может и сгодится идея перебивать оператора ().
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[20]: Адрес метода
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.07.01 21:33
Оценка:
Здравствуйте IAZ, вы писали:

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



IAZ>Сомневаюсь, что такая статья необходима — зачем переливать из пустого в порожнего: так нельзя попробуйте по другому. Это тянет не больше чем на маленький FAQ.


Так это зависит от количества написанного? А вопрос этот (в той или другой форме) подымается очень часто. Но все равно спасибо за мнение.

IAZ>А если все таки написать статью, то неизвестно как она повлияет на неокрепшую психику начинающего программиста.


Ну, на психику влиять можно по разному. :) Если хорошенько объяснить, что хорошо, а что плохо, что можно смело использовать, а что с осторожностью... Главный вопрос понимания того, что есть и чего нет! А выводы лучше оставить читателю.

IAZ>Из-за отсутвия опыта и знаний он может это использовать не поназначению.


Ну, батенька — это уже цензура какая-то! Эдак и про нож можно сказать, что его описывать нельзя — "А вдруг его кто не по назначению использует?". :)

IAZ>А чтобы охватить все аспекты этой проблемы одной статьи мало.


А, тут Вы ошибаетесь. Думаю одной статейки будет как раз, а если и не влезет, сделаем сериал. :)

С уважением, Влад.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: Адрес метода
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.07.01 21:42
Оценка:
Здравствуйте IAZ, вы писали:

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


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


IAZ>Очепяток тут хватает, я бы не стал на этом заострять внимание :)


Я не об опечатка (сам не без греха). Я о противоречии самому себе в одном обзаце, и о недоверии компилятору. :)

IAZ>Вопрос был в следующем: присвоить указателю на глобальную функцию указатель на функцию-член. Стандарт это не позваляет. Во многих случаях во время исполнения не происходит добавления этого смещения — добавляется при компиляции. Так что реально такая функция становиться самой обычной (как глобальная). Но еще раз сошлюсь на стандарт: он не позволит обращаться с таким указателем как с обычным. Но asm'е это можно успешно преодалеть, только работать будет не всегда.


Не-аа, вопрос был о том, что в С++ не реслизована возможность вызвать фукцию класса по универсальному указателю! Указатель на функцию класса нафих не нужен, а нужен указатель следующего вида:

this // некоторого экземпляра
func_ptr // указатель на функцию

причем если задавать эти параметры во время когда объект создан, то нет проблем ри в вычислении правильного this, ни в вычислении правильного адреса функции (даже если она будет виртуальной). Идея проста как 3 копейки но увы...

А вызов он хоть будь трижды виртуальным все равно вревратится в:

f1(this, xxx);
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Адрес метода
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 23.07.01 03:47
Оценка:
VD>Кстати, а ни кто не пробывал создать унивирсальный указатель на функцию любого класса. На asm-е я такие штуки прокатывал, а как на Плюсах?

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

простейший вариант выглядит так

пардон, что со шрифтами фигня.

////////////////////////////////////////////////////////////////////////////////
//&Ecirc;&euml;&agrave;&ntilde;&ntilde;-&ccedil;&agrave;&atilde;&euml;&oacute;&oslash;&ecirc;&agrave; &auml;&euml;&yuml; &icirc;&aacute;&uacute;&yuml;&acirc;&euml;&aring;&iacute;&egrave;&yuml; &ograve;&egrave;&iuml;&agrave; __closure_think

namespace closure_v1{ //&egrave;&ntilde;&ecirc;&euml;&thorn;&divide;&agrave;&aring;&igrave; &aring;&atilde;&icirc; &egrave;&ccedil; &iuml;&eth;&icirc;&ntilde;&ograve;&eth;&agrave;&iacute;&ntilde;&ograve;&acirc;&agrave; &egrave;&igrave;&aring;&iacute; structure

struct t_closure_think
{
void f(){;}
void f()const{;}
};

typedef (t_closure_think::*__closure_think)();
};//namespace closure_v1

////////////////////////////////////////////////////////////////////////////////
// &Ecirc;&Euml;&Agrave;&Ntilde;&Ntilde;&Ucirc; &Auml;&Euml;&szlig; &Oacute;&Iuml;&ETH;&Agrave;&Acirc;&Euml;&Aring;&Iacute;&Egrave;&szlig; &Icirc;&Aacute;&ETH;&Agrave;&Aacute;&Icirc;&Ograve;&times;&Egrave;&Ecirc;&Icirc;&Igrave; &Aacute;&Aring;&Ccedil; &Agrave;&ETH;&Atilde;&Oacute;&Igrave;&Aring;&Iacute;&Ograve;&Icirc;&Acirc;

template<class TObj>
class t_closure_0_caller
{
public: //typedefs
typedef closure_v1::__closure_think t_think;

typedef void (TObj::*TMemFunc)();

public:
static void call(void* obj,t_think think)
{
assert(obj!=NULL);
assert(think!=NULL);

((*(TObj*)obj).*(*(TMemFunc*)&think))();
}
};

//------------------------------------------------------------------------------
class t_closure_0
{
public: //typedefs
typedef t_closure_0 t_closure;
typedef closure_v1::__closure_think t_think;

//&oacute;&ecirc;&agrave;&ccedil;&agrave;&ograve;&aring;&euml;&uuml; &iacute;&agrave; &ocirc;&oacute;&iacute;&ecirc;&ouml;&egrave;&thorn;, &ccedil;&agrave;&iacute;&egrave;&igrave;&agrave;&thorn;&ugrave;&oacute;&thorn;&ntilde;&yuml; &acirc;&ucirc;&ccedil;&icirc;&acirc;&icirc;&igrave; &igrave;&aring;&ograve;&icirc;&auml;&agrave;
typedef void (*t_caller)(void* obj,t_think);

private:
void* obj;
t_think think;
t_caller caller;

public:
t_closure_0()
:obj(NULL),think(NULL),caller(NULL){;}

t_closure_0(void* obj,t_think _think,t_caller _caller)
:obj(obj),think(_think),caller(_caller){;}

t_closure& operator = (int x)
{
assert(x==0); //&ograve;&icirc;&euml;&uuml;&ecirc;&icirc; NULL
return *this=t_closure();
}

t_closure& operator = (void* pv)
{
assert(pv==0); //&ograve;&icirc;&euml;&uuml;&ecirc;&icirc; NULL
return *this=t_closure();
}

void operator () ()const
{
assert(caller!=NULL);
caller(obj,think);
}

operator bool () const
{
return obj!=NULL && think!=NULL && caller!=NULL;
}

bool operator ! () const
{
return !(bool)*this;
}
};//class t_closure_0

//------------------------------------------------------------------------------
//&ntilde;&icirc;&ccedil;&auml;&agrave;&iacute;&egrave;&aring; &oacute;&ecirc;&agrave;&ccedil;&agrave;&ograve;&aring;&euml;&yuml; &iacute;&agrave; &icirc;&aacute;&eth;&agrave;&aacute;&icirc;&ograve;&divide;&egrave;&ecirc;
template<class TObj>
t_closure_0 make_closure(TObj* obj,void (TObj::*MemFunc)())
{
typedef closure_v1::__closure_think t_think;
typedef t_closure_0_caller<TObj> t_caller;
typedef t_closure_0 t_closure;

return t_closure(obj,*(t_think*)&MemFunc,t_caller::call);
}
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[10]: Адрес метода
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 23.07.01 03:49
Оценка:
после отправки cтало выглядеть еще хуже :(
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[21]: Адрес метода
От: IAZ http://iaz.simb.ru
Дата: 23.07.01 18:36
Оценка:
Здравствуйте VladD2, вы писали:

IAZ>> И даже тогда остается покрайне мере несколько ситуаций когда они (реализации) будут кардинально не верны.

VD>Т.е. если есть asm-вставка, то обязательно когда ни будь грохнет? А как же половина MS CRT — написанная на asc-е? И куски из ATL?

Разве мало случаев когда грохает?

VD><skip> а на асм-е я там совсем примитивную вещь делал – 4-е байта копировал. Неужели от этого могут быть какие-то проблемы? Да и спецификация thiscall-а полностью описана. Так что проблема здесь может возникнуть, только если первые 4-е байта указателя на функцию класса будут содержать что ни будь отличное от указателя на функцию.


Да, именно, 4 байта. А если указатель на функцию занимает 8 или 12 байт? Тут прямая зависимость от компилятора. Например, возьмет он и оптимизирует код вызова функции, кастрирует к 4 байтам, там где предполагалось 8. А asm вставку он, разумеется, менять не может. И все, полетел asm-вызов.

VD>Будет возникать проблема с переносимостью разобрались бы с конкретным компилятором и... Ну, а asm здесь вообще не причем напишите такой код хоть на C, хоть на C++, хоть на VB, ровным счетом ни чего не изменится. Здесь налицо зависимость от компилятора.


При переносе на другую платформу (Ex. I64) программу на C/C++ возможно придется просто перекомпилировать. Ну а на asm’e, сами понимаете, переписать.

IAZ>>Средство "указатели на функции экземпляра объекта" подразумевает две вещи:

IAZ>>1. указатель на объект
IAZ>>2. указатель на функцию в _этом_ объекте
IAZ>>Все это присутствует в С++

VD>Ага. Но по отдельности. И указатель на функцию одного класса нельзя нормальными средствами преобразовать в указатель на функцию другого объекта.


При вызове они соединяются :)

IAZ>>Избавивщись от первого мы избавляемся от самого объекта. Так может программировать тогда С? Или использовать глобальные функции, или статические.


VD>Причем здесь C и глобальные функции я не знаю, но именно "от первого" и избавился СтраусТруп при создании своих указателей. Может он подразумевал, что указатели на функции разных классов можно будет попросту приводить друг к другу? Я не знаю но реалии жизни, в лице VC, плюют на все предпложения...


Я это к тому, что в С и глобальные и статические функции можно приводить к void*, а, соответственно, и друг к другу. А в С++ функция принадлежит классу, а вызов осуществляется при помощи объекта этого класса. Как в стандарте написано, так и реализовано. VC++ в этом случае точна.

IAZ>> Интерестно какова сложность проектирования C++ и ATL (MFS & etс.)? Где и кем используется С++ и ATL? В конце концов ATL это всего лишь библиотека которую написали как смогли, на том _подмножестве_ C++ которое знали эти программисты и которое поддерживает этот компилятор.


VD>Ннн-да, думаю, что программисты эти были одними из лучших в мире. По крайней мере, нас с Вами они, похоже, превосходят. Так, что можно не сомневаться, что C++ они знают в совершенстве. И не в реализации дело.

<skip>
VD>И почему Вы думаете, что "ATL это всего лишь библиотека которую НАПИСАЛИ КАК СМОГЛИ", а C++ это незыблемая вещь которую написали бессмертные гении? Страуструп совсем непохож на Моцарта, да и у последнего не все произведения становились бессмертными. Лажался Страуструп (при создании этого языка) не мало. Так что мы всего лишь замазываем за ним дырки. Не, я понимаю, что многих идей просто не было в то время, например сборки мусора, но указатели на функции он попытался перенести в объектно-ориентированную среду, но … но облажался. Получилась никчемная реализация (из хорошей идеи).

Да я и не говорил что C++ это незыблемая вещь которую написали бессмертные гении. Но С++ разрабатывается (он продолжает развиваться) с 1983 года. Причем группой очень умных людей. Помимо Страуструпа, интеллектуальный уровень которого мы объективно не сможем оценить, но достаточно того что он задумал этот язык, там есть и Керниган и Ричи и Кениг, т.е. те кто приложил руку :) к созданию С и Unix. А кто участвовал в проектировании и реализации ATL, MFC, Windows? Черт их знает. Я точно не знаю.
Сборка мусора существует с начала появления информатики, как теории. Где она была впервые реализована, навскидку сейчас не вспомню (Algol, PL, LISP?) но точно до 80-х. А указатели на функции он никуда не переносил, какие в С были такие и остались в С++. Было только принято о не возможности приведения функций-членов к void*. Из-за их потенциональной опастности. Многие "недоработки" и "ошибки" С++ происходят из-за не возможности отойти от С на достаточно большое растояние.

VD>А, за Ваш совет (в другом постинге) спасибо. Правда, пока я не разобрался можно ли из него почерпнуть чего интересного, но все равно спасибо!

VD>Будет время, попробую по колдовать. Может и сгодится идея перебивать оператора ().

Особенно посмотрите на концовку. Это чистый callback и даже немного delegate :). Правда приминим только для С++ программ.

Вам тоже спасибо за интерестный диалог.
С уважением, IAZ.
Кто ищет то всегда найдет!
Re[21]: Адрес метода
От: IAZ http://iaz.simb.ru
Дата: 23.07.01 18:43
Оценка:
Здравствуйте VladD2, вы писали:

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


IAZ>>Сомневаюсь, что такая статья необходима — зачем переливать из пустого в порожнего: так нельзя попробуйте по другому. Это тянет не больше чем на маленький FAQ.


VD>Так это зависит от количества написанного?


Зависит :)

IAZ>>Из-за отсутвия опыта и знаний он может это использовать не поназначению.


VD>Ну, батенька — это уже цензура какая-то! Эдак и про нож можно сказать, что его описывать нельзя — "А вдруг его кто не по назначению использует?". :)


IAZ>>А чтобы охватить все аспекты этой проблемы одной статьи мало.


У меня было два предложения но записанные в одну строку :) Поскольку программер неопытный ему надо представить проблему как можно шире. Я согласен: пусть сам решает.

VD>А, тут Вы ошибаетесь. Думаю одной статейки будет как раз, а если и не влезет, сделаем сериал. :)


VD>С уважением, Влад.


С уважением, IAZ.
Кто ищет то всегда найдет!
Re[10]: Адрес метода
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.07.01 01:23
Оценка:
Здравствуйте Коваленко Дмитрий:

Я тут тоже поизглялся, но результат мне еще не очень нравится. Вызов и инициализация получается красивыми, а вот задание самой функции нет. Так что свой вариант пока не приведу, но Ваш посмотреть очень хочется. То что получилось ... читается очень тяжело. :) Может еще одну попытку? Да через какой нибудь нотпэд?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.