Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > механизм виртуальных функций (не работает:() |
Автор: Podarochek 23.5.2008, 02:37 | ||
подскажите ошибку? ![]()
|
Автор: mes 23.5.2008, 03:18 | ||
|
Автор: Podarochek 23.5.2008, 03:24 | ||
что значит эта ошибка: Error 1 error C2440: 'initializing' : cannot convert from 'void (__thiscall A::* )(void)' to 'void (__cdecl *)(void)' Добавлено через 3 минуты и 30 секунд тут же все пом ок:
|
Автор: Podarochek 23.5.2008, 03:39 |
хм.. какой же нужно создать указатель? |
Автор: mes 23.5.2008, 03:55 | ||
сорри что ввел в заблуждение синтаксисом подразумевалось что вместо void (**ftable)(); должна быть примерно void (A::**ftable)() а вобше имхо что подобный способ реализации виртуальных функций выбран не совсем правильно P.S еше и звездочки перепутал..помойму засиделся я слишком |
Автор: mes 23.5.2008, 05:23 | ||
вот набросал еше один вариант реализации механизма виртуальных функций.
P.S Podarochek, ты этой темой занялся из собственного любопытства или это задание? |
Автор: mes 23.5.2008, 11:46 | ||
В этом примере каждый объект хранит таблицу виртуальных методов. В связи с этим возможна ситуация что у двух объектов одного класса будут вызываться разные методы - что не соответствует реальным виртуальным функциям. Будет свободное время - переделаю. |
Автор: mes 23.5.2008, 12:48 | ||
вот со статической vtable для каждого класса..
|
Автор: xvr 23.5.2008, 13:29 | ||||
Ошибка в том, что это именно иллюстрация и не надо рассматривать это как программу на С++. Если надо сделать по этой иллюстрации реальную программу, то ее надо делать на С (ибо в С++ это все и так есть) из этого исходника, предварительно 'обработав его напильником' до состояния правильного С сорца. |
Автор: mes 23.5.2008, 13:42 | ||
блин как я читаю... ![]() а как же тогда классы ?? ![]() ![]() |
Автор: mes 23.5.2008, 13:58 |
подумав, все таки пришел к выводу, что иллюстрацию надо делать на С++, без использования встроенных виртуальных функций для демонстрации процесса "обратного"(callback) вызова нужной реализации потомка из базового класса. |
Автор: Podarochek 23.5.2008, 15:19 | ||||
оператор поставил в protected всеравно отстался вопрос:
его реально решить в этой "иллюстрации"????
стоит задача продемонстрировать механизм, никакой практической задачи. Как С++ никто не рассматривает об этом говорит постановка задачи . Добавлено через 5 минут и 43 секунды кстати..ссори что не по теме..подскажите что за ошибка: Error 3 error LNK2001: unresolved external symbol "public: virtual double __thiscall Employee::earning(void)const " (?earning@Employee@@UBENXZ) 123.obj |
Автор: mes 23.5.2008, 15:35 | ||||||
а при чем тут ограничение доступа (protected) ? ты пытаешься привести метод к указателю на функцию решений два : 1. заменить массив указателей на функции массивом указателей на нужный тип метода или 2. запихивать в массив не методы, а статические функции (но они не смогут работать с членам класса) Добавлено через 5 минут и 45 секунд
такой механизм можно продемонстрировать только в OOП (там где есть наследие) - так что классический Си отпадает
линкер не нашел тела функции Добавлено через 14 минут и 43 секунды а чем тебя не устраивают примеры приведенные мной? (хочу заметить что твой пример далеко не Сишний) |
Автор: mes 23.5.2008, 15:53 |
а если реализовывать на Си то надо реализовывать классы и наследственность |
Автор: Podarochek 23.5.2008, 16:02 | ||
ссори, может я не так выразился...конечно же реализация будет предполагать С++, но имеется в виду раскрыть карты С++ и показать механизм явно (таблицу указателей). как сказал xvr этот механизм и так есть уже в С++ Добавлено через 13 минут и 5 секунд Я думаю по теме (еще одна ошибка) хоть убей, не могу понять что от меня хотят, кажись все реализованно как говорят по учебнику, а пишет: Error 3 error C2259: 'Boss' : cannot instantiate abstract class Error 4 error C2259: 'CommissionWorker' : cannot instantiate abstract class и все...:( Добавлено через 14 минут и 32 секунды
|
Автор: mes 23.5.2008, 16:18 | ||||
ну в принципе именно так я и понял задание с самого начала..потом сбили дополнительные высказывания )) кстати насчет vtable - на самом деле таблица не представлена в виде набора массива однотипных указетелей а виде набора разных структур, содержаших разнотипные указатели вот доработал еше чтоб больше походило на реальный механизм - хотя и еше есть что доработать:
|
Автор: Podarochek 23.5.2008, 16:33 |
спасибо mes буду разбираться по поводу второго примера подскажешь? |
Автор: mes 23.5.2008, 16:41 | ||||||
у тебя в этих классах есть абстрактные функции, а такие обжекты создавать нельзя
Добавлено через 1 минуту и 22 секунды глянул в код - так у тебя у самого черным по белому написано
![]() |
Автор: Podarochek 23.5.2008, 17:07 | ||
ну да базовый класс создан абстрактным, а производный класс например я изменил ->(теперь без virtual) //класс CommissionWorker, производный от класса Employee class CommissionWorker : public Employee { public: CommissionWorker( const char *, const char *,double = 0.0, double = 0.0,int = 0 ); void setSalary( double); void setCommission( double); void setQuantity( int); double earnings() const; void print() const; private: double salary;//базовая заработная плата за неделю double commission;//комисионные от продажи одного изделия int quantity; //количество проданных изделий за неделю }; всеравно ошибки. Объекты производных классов разве нельзя создавать? Добавлено через 4 минуты и 27 секунд
например объект А1 ob; |
Автор: mes 23.5.2008, 17:33 |
можно создавть объект и в стеке и по new при условие что у класса нет абстрактных методов.. пояснение: если у предка есть абстрактные методы - то они все должны получить реализацию у потомка слово virtual важно только для первого употребления, после этого у потомков метод с таким именем всегда будет считаться виртуальным надо не интерфейс изменять а добавить реализцию к чистым методам Добавлено через 1 минуту и 8 секунд P.S зря ты обе темы в одной ветке запостил .. путает |
Автор: Podarochek 23.5.2008, 17:50 |
![]() earnings вместо earning!!! Я балбес. Конечно они должны быть одинаковы...откуда взяласт s до сих пор не могу понять ![]() Добавлено через 2 минуты и 3 секунды о втором посте(т.е. ответвлении от основной темы) забыли...прошу прощения!!! ![]() |
Автор: mes 24.5.2008, 15:42 | ||
Вот еше раз доработал код, на этот наконец то отделил технические операции от представления класса : этот вариант можно считать законченым (потому как для дальнейших улучшений требуются шаблоны, а это будет вне задания ) ![]()
|
Автор: mes 24.5.2008, 18:12 | ||
мелкие доработки перегрузка некоторых функций (возврашаюших vtable) по типу наследование прокси-функций а также убрал зависимость от порядка инициализации
|
Автор: mes 24.5.2008, 20:21 | ||
Podarochek, не думал, что меня так зацепит эта тема )) вот еше немного добавил в илюстрацию теперь есть: псевдо pure-абстрактный класс, и два класса: один с частичной другой с полной перегрузкой абстрактных методов
|
Автор: mes 24.5.2008, 23:00 | ||||
Ну вот дошли и до извращений . Специально для любителей таких вещей : main.cpp :
A_vtable.h :
теперь есть возможность "переключать" код между режимами (за/раскомментировать строку #define VIRTUAL_ILLUSTRATION ) : 1. реальные виртуальные методы 2. псевдо виртуальные методы (реализованые вручную (без помощи) компилятора ) Хотя реальной пользы от программы нет - мне кажется он может помочь понять механизм работы виртуальных методв (у тех у кого проблемы) теперь весь код псевдо производимый компилятором выделен и можно пронаблюдать различия и увидеть сколько черной работы он(компилятор) делает за программиста. |
Автор: xvr 25.5.2008, 10:32 | ||
Круто ![]() Предлагаю в качестве дальнейших шагов рассмотреть множественное наследование, виртуальные базовые классы и RTTI/dynamic_cast ![]() PS. Предлагаю предыдущий пост поместить в FAQ. |
Автор: mes 25.5.2008, 12:16 | ||||||
учел замечания и убрал лишнее. буду рад комментам
надо будет подумать ( когда будет свободное время ) |
Автор: xvr 25.5.2008, 20:12 | ||||||
Коментарий: способ оформления таблицы виртуальных функций (как это делает компилятор)
т.е. какой либо код для построения таблицы виртуальных функций отсуствует вообще, только присваивание адреса в конструкторе |
Автор: mes 25.5.2008, 20:56 | ||
то есть разница что компилятор строит ее в компил-тайм, а в моем примере в рантайме ? ну так оно и есть: в одном случае таблица строится управляемая инструкциями типа virtual во время парсинга кода во втором строится за счет рант-тайм кода конструкторов также наверно то что используются прокси функции для вызова ? ну так в реальном (откомпиляторном виде) все функции приведены к такому виду и компилятору не приходится мучаться а нам приходится его обманывать )) ![]() |
Автор: Podarochek 26.5.2008, 09:36 |
Скопировал ВСЕ! ![]() Спасибо участникам за столь подробный анализ. mes ![]() Я думаю вопрос решен. вперед разбираться с примерами ![]() |
Автор: mes 26.5.2008, 10:01 |
все не нужно - только последний приведенный код - он самый понятный и "правильный" (насколько можно так сказать) ![]() |
Автор: Podarochek 26.5.2008, 10:22 | ||
я думаю, что полезен не только готовый вариант, но и ход размышлений (свои+чужие ошибки)= счастье! |