Войти
ПрограммированиеФорумОбщее

Полиморфизм с++ Что не так с этим кодом? (5 стр)

Страницы: 1 2 3 4 5 6 Следующая »
#60
11:45, 4 фев. 2012

Kartonagnick
>Вот с этого момента поподробнее, пожалуйста.

Т.е. вред от такого подхода не пугает.
хорошо.
1. Из-за того что c++ работает исключительно с объявленными типами, делаем прототип функции
void *Test();
после
Base* ptr = new Derived;
затем Test=ptr+testshift;// где testshift смещение функции test от начала ptr.
// а как его высчитать - изучаем документацию на конкреный компилятор.

затем просто вызываешь *Test() и вызовется (ptr->clone())->Test(). Типа Derived.

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

!НО. Так делать крайне не рекомендуется.
1. Это уход от приципов C++
2. Вероятность выпустить бажный код - 99.999%.

Данную херню можно попробовать только для самообучения и не более.
Сам компилятор создали чтобы все эти смещения высчитывались автоматом, чтобы в итоговой программе было минимум ошибок. А чтобы лазить из базового класса к потомкам придумали виртуальные функции и dinamic_cast.


#61
11:54, 4 фев. 2012

KKH
> затем Test=ptr+testshift;// где testshift смещение функции test от начала ptr.
Нее, это фигня какая-то. Адрес метода же не в самом объекте хранится.

#62
13:09, 4 фев. 2012

[A][R][T]
Не буду спорить, т.к. достоверно не помню. Но если функции (методы) и переменные статические (хотя какая разница, на динамические указатели тоже внутри объекта), разве он их не подряд в одну память кладёт при создании очередного объекта ? Возможно я отстал от жизни ... Смысл хапать память кусками из разных областей ... её даже кешировать не удобно тогда.

Я баловался раньще, возможно мне везло. К ptr прибавлял по 4 и получались все указатели начиная с первой функции и заканчивая последней переменной. это был MSVC.

>Адрес метода же не в самом объекте хранится.
Что-то [A][R][T] я в этом сильно сомневаюсь. Лень на это тратить суботу, чтобы вспомнить механизм.

Помню одному человеку очень дого доказывал что в dll можно выделить память а в exe освободить. Кончилось тем что он не верил в рабоу программы. И очень дого цепялся к тому что я пользовался не new и delete. И в доказательство своей правоты, просил это сделать new и delete. Так что с тех пор тратить время на споры - не хочу.

#63
14:18, 4 фев. 2012

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

#64
18:55, 4 фев. 2012

Резюмируя: через указатель на базовый класс, невозможно толкнуть не_виртуальный метод потомка, через "смещение".
Просто потому, что объект-потомок не хранит внутри себя информацию о своих не_виртуальных методах.

#65
19:24, 4 фев. 2012

Kartonagnick
> Резюмируя: через указатель на базовый класс, невозможно толкнуть не_виртуальный
> метод потомка, через "смещение".
  Зачем смещение?
  http://ideone.com/5kaBx - вызвали функцию одного класса, используя объект другого класса.

  P.S. Возможно, не самый удачный пример, так как в качестве указателя на объект в данном случае можно использовать хоть NULL. Но так как идея всё равно ничего общего с практикой не имеет, зато представление даёт, то исправлять не буду.

#66
20:02, 4 фев. 2012

Zefick
> Возможно, не самый удачный пример

Это не самый удачный пример, потому что там используется явное приведение типов.
То бишь, программист сам ручками указывает метод какого класса он толкает.

А нужно толкнуть не_виртуальный метод объекта, ничего не зная о его реальном типе.


--------------
Проблема на самом деле глубже, чем кажется. Проиллюстрирую на примере:

Что бы вытащить на свет божий "реальный тип" объекта в рантайме, нужно как минимум запустить нечто, имеющее вид:

template<class type> type& GetFact(void* pTarget)  { return  *((type*) pTarget); }

--------------

Проблема не в том, как идентифицировать сам тип объекта. А в том, как этот самый тип вытащить наружу?

Допустим, есть такая лажа:

switch (ID)
{
   case(TYPE_Derrived): 
    { 
             /*и чего? И как? Ну узнали вы, что тип - derived, что дальше? Как этот тип выкинуть наружу?*/           
    }
}

Допустим, мы можем запомнить адрес функции GetFact<TYPE_Derrived>(void* pTarget)
А с наружи по этому указателю уже запустят саму функцию, и получат тип.

Как можно запомнить функцию?

Ведь,  Derived& GetFact(void* pTarget), и NoDerived& GetFact(void* pTarget) потребуют два разных указателя.

А передача данных о функции через какое то "нечто" должно иметь единственный точный тип.


Можно было бы как нибудь запускать функции через "волшебный" указатель, которому не требуется знать о возвращаемом типе функции, тогда проблема была бы решена.
И можно было бы запросто повесить на с++ и динамику, и рефлексию.

#67
21:45, 4 фев. 2012

Kartonagnick
>Можно было бы как нибудь запускать функции через "волшебный" указатель, которому не требуется знать о возвращаемом типе функции, тогда >проблема была бы решена.

К сожалению нет и связанно это с существующими моделями функций, которые оговорены.
Читай __cdecl, __stdcall, __fastcall. И тогда станет ясно почему и тогда можно будет изобретать свою модель, если не пропанет желание.

#68
22:04, 4 фев. 2012

Kartonagnick
> Проблема не в том, как идентифицировать сам тип объекта. А в том, как этот
> самый тип вытащить наружу?
если идентифицировал, то приводи кастом, можно даже статическим, он прекрасно ориентируется в иерархии классов, если нет множественного наследования : )

> Как можно запомнить функцию?
указатель на функцию или "делегат", можно их хранить отдельно "стопочкой" : )
позволяет вызывать любую функцию у экземпляра любого класса с любыми аргументами (помимо тех, что заявлены в сигнатуре)

и да, в плюсах таки есть своя "магия", но не такая тупорылая, что компилятор все разруливает без знания типа, а "всемогущий" std::tr1::bind : ))

З.Ы.
Kartonagnick
> Ну це пись пись же умеет как то определять фактический тип объекта.
а позвольте спросить скока часов "налетал" на плюсах, чтобы так фамильярно? ; )

а то вона ККН с почти десятью годами опыта совсем забыл про извращённый манглинг, что выделывает компилятор чтобы хранить функции "стопочкой" в укромном месте : )

#69
22:58, 4 фев. 2012

Sh.Tac
>а то вона ККН с почти десятью годами опыта совсем забыл про извращённый манглинг
я про него и не знал, а если и читал, то действительно забыл, т.к. никогда не пользовался такой фичей. Хватало и приведения типов и кастов и виртуальных методов. В редких случаях статик.

#70
4:26, 5 фев. 2012

>> LuckyMan: о что должен делать newFoo.test(); если у "настоящего" типа нет такого метода?
>> Kartonagnick: LuckyMan, не о том речь, что он должен, или не должен.
С ведерком попкорна в руках терпеливо ожидаю того момента, когда топикстартера наконец озарит, что он не имеет ни малейшего понятия, что произойдет, если у объекта вызываемого метода нет, не было и не предвидится...

...и лишь один момент омрачает ожидание:
>> Kartonagnick: LuckyMan, представь себе, что у тебя есть на руках Base* ptr; Ты не знаешь его настоящего типа. Но знаешь, что у него есть метод test();
ВНЕЗАПНО, мы точно знаем, что метод есть. Иначе говоря, они все имеют по меньшей мере один общий интерфейс.

Более того, не быть метода у объекта не может в принципе. Иначе пришлось бы до вызова по тем или иным способом полученному реальному типу объекта делать выводы о правомерности вызова. Но сравнения с прописанными ручками константами (как, например, константой-типом в dynamic_cast) -- моветон и полный Содом по мнению все того же топикстартера. Выходит, проверки быть не может, а раз так, значит они все железобетонно имеют по меньшей мере один общий интерфейс, помимо Base или чего еще там. Вправе ли я предполагать, что концепция наличия нескольких интерфейсов у объекта уж очень тяжело укладывается в ваш шаблон, мсье Kartonagnick?

Хотя нет, я все-таки хочу увидеть вызов несуществующей функции. Верно было подмечено: в голову, в голову!

#71
5:10, 5 фев. 2012

Cfyz
> ВНЕЗАПНО, мы точно знаем, что метод есть.

template<class T> Do(T& target) { target.Work(); }

Что бы запустить метод любого объекта, программист как минимум должен знать что именно он запускает. Компилятор "Work()" за программиста не впишет.
А вот знать его фактический тип совершенно не обязательно.

Cfyz
>Иначе говоря, они все имеют по меньшей мере один общий интерфейс.

template<class T> Do(T& target) { target.Work(); } 

На кой болт любому из запускаемых таким образом объекту нужен голимый общий интерфейс? Ключевое слово "общий".
Вполне достаточно иметь свой собственный, который может быть ни с кем никак не связанный. Класс не обязан иметь родственников. Ключевое слово - "иметь".

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

#72
5:28, 5 фев. 2012

Kartonagnick
> А вот знать его фактический тип совершенно не обязательно.
Зависит от языка. В С++ как раз обязательно. Это в Питоне и ObjectiveC и прочих не обязательно. Только у них метаинформация о типе есть. И метаинформация добавляется не "волшебными" указателями, а на уровне транслятора.
Kartonagnick
> На кой болт любому из запускаемых таким образом объекту нужен голимый общий
> интерфейс? Ключевое слово "общий".
> Вполне достаточно иметь свой собственный, который может быть ни с кем никак не
> связанный. Класс не обязан иметь родственников. Ключевое слово - "иметь".
За структурной типизацией вы обратились не по адресу.
И за динамической тоже.
А переносить приемы языков с динамической типизацией на статически типизированые - имхо, вполне оправданно считается дурным тоном.

#73
5:31, 5 фев. 2012

Grey304
> В С++ как раз обязательно.

template<class T> Do(T& target) { target.Work(); }

На кой болт программисту знать тип объекта? Вполне достаточно знать, что у объекта есть метод.

#74
5:37, 5 фев. 2012

Kartonagnick
> На кой болт программисту знать тип объекта? Вполне достаточно знать, что у
> объекта есть метод.
Вы что, только с динамически типизированными языками и знакомы?
Плюсы - статически типизированный. И такой ерунды не допускают. Это, так скать, врожденное его свойство. Как и многие другие статически типизированые. Вообще, приведите примеры языков, где эта фича реализована. А то окажется, что это все динамически типизированые. (Или структрная))
А шаблоны - сущность времени компиляции. И компилятор как раз знает все в момент инстанцирования.

Страницы: 1 2 3 4 5 6 Следующая »
ПрограммированиеФорумОбщее

Тема в архиве.