Комментарии 21
универсальность, безусловно, дело хорошее, но столько текста ради константы…
чем дальше, тем с++ все больше становится языком для компиляторов, а не для людей.
чем дальше, тем с++ все больше становится языком для компиляторов, а не для людей.
+1
Это должно быть скрыто в недрах кода компилятора, а наружу торчать ключевое слово nullptr и тип его. Не берусь судить о «человечности» C++, но столько текста у меня это именно результат:
а) Отсутствия C++ 11 и велосипедостроения.
б) Моей дотошности до соответствия nullptr стандарту.
в) Багов старых компиляторов.
а) Отсутствия C++ 11 и велосипедостроения.
б) Моей дотошности до соответствия nullptr стандарту.
в) Багов старых компиляторов.
+3
Возможно я немного не в тему, но уже долгое время мучает вопрос. Вы написали, что void * по стандарту должен вмещать в себя любой указатель. Касается ли это указателей на виртуальные методы? И где вообще можно почитать про sizeof указателя на виртуальный метод?
0
Если кратко то ответ «нет». Указатели на члены класса это отдельные указатели и их нельзя держать в void*. Для этого есть тип указатель-на-член-класса со своим объявлением. У меня речь идет о том что nullptr должен уметь преобразовываться в любой указатель, это обратная операция. По стандарту sizeof(nullptr) == sizeof(void*), потому речь идет именно о указателе void.
sizeof виртуальной функции-члена класса будет в большинстве реализаций больше чем sizeof указателя на void, т.к. по сути обычно это структура, содержащая таблицу адресов виртуальных функций. По стандарту это implementation-defined и разработчики компилятора вольны делать любого размера и представления такие указатели.
Читать — это вам в текст стандарта разве что или доверять выдержкам из него на всяких stack overflow.
sizeof виртуальной функции-члена класса будет в большинстве реализаций больше чем sizeof указателя на void, т.к. по сути обычно это структура, содержащая таблицу адресов виртуальных функций. По стандарту это implementation-defined и разработчики компилятора вольны делать любого размера и представления такие указатели.
Читать — это вам в текст стандарта разве что или доверять выдержкам из него на всяких stack overflow.
+2
Благодарю за ответ. Это может понадобиться, если придётся велосипедить рефлексию/интроспекцию в рамках старых стандартов. Но, как я понимаю, всё равно любой метод (виртуальный или нет) будет представлять из себя обычную «thiscall» функцию. Т.е. имея правильный указатель на класс можно всё равно запихнуть указатель на метод в void*.
0
На тему того как компактно хранить указатели на свободные функции и функции-члены класса можете взглянуть на fast delegates и понять какой это цирк, а так же на мое расширение всего этого безобразия .
Не понимаю в чем «правильность» может быть у указателя на класс. Указатель на функцию-член класса в void* запихнуть не получится, т.к. у него размер не тот, вы информацию потеряете. А вот хранить связку this_pointer + указатель-на-функцию-член это пожалуйста.
Не понимаю в чем «правильность» может быть у указателя на класс. Указатель на функцию-член класса в void* запихнуть не получится, т.к. у него размер не тот, вы информацию потеряете. А вот хранить связку this_pointer + указатель-на-функцию-член это пожалуйста.
+1
Под правильностью я понимал случаи с полиморфными классами со сложной иерархией наследования. Насколько я понимаю, нельзя «в лоб» получить нужный тип из
Допустим, у нас есть виртуальный метод
Но я думаю, что мне лучше не вас в комментариях грузить, а пойти покопать информацию про способы вызова функций. Заранее спасибо.
void *
при помощи static_cast
при ромбовидном наследовании. Но я не про это.Допустим, у нас есть виртуальный метод
MyClass::Foo( args... );
. Соответственно при его вызове неявно первым аргументом передаётся this. Т.е. зная адрес метода в памяти и зная this
этот метод можно вызвать как обычную функцию. При этом адрес метода всё равно будет равен разрядности платформы, т.е. sizeof(void*)
. Это верно?Но я думаю, что мне лучше не вас в комментариях грузить, а пойти покопать информацию про способы вызова функций. Заранее спасибо.
0
Не вижу проблемы скастовать к нужному типу. Так что либо я вашу задачу не понимаю, либо я вашу задачу не понимаю.
Это верно, естественно адреса будут в итоге по разрядности платформы. На этот счет коллеги лучше знакомые с ассемблером вам наверняка много чего занимательного расскажут. Верно и то, что неявно передается this как аргумент вызываемой функции. Но только это к языку C++ и типу языка void* уже имеет слабое отношение. Этими вещами занимается компилятор с транслятором, и как они это делают зависит от того как разработчики компилятора это реализовали. Если вас интересует внутреннее представление виртуальных таблиц в разных компиляторах, то я вам ссылку привел на SO выше.
А как покопаете информацию так напишите статью и поделитесь раскопками. Мне будет интересно, уверен сообществу тоже.
Это верно, естественно адреса будут в итоге по разрядности платформы. На этот счет коллеги лучше знакомые с ассемблером вам наверняка много чего занимательного расскажут. Верно и то, что неявно передается this как аргумент вызываемой функции. Но только это к языку C++ и типу языка void* уже имеет слабое отношение. Этими вещами занимается компилятор с транслятором, и как они это делают зависит от того как разработчики компилятора это реализовали. Если вас интересует внутреннее представление виртуальных таблиц в разных компиляторах, то я вам ссылку привел на SO выше.
А как покопаете информацию так напишите статью и поделитесь раскопками. Мне будет интересно, уверен сообществу тоже.
0
Нет. Одна из возможных форм указателя на виртуальный метод — это смещение относительно начала vtable. Плюс нужно где-то хранить тип указателя, чтобы понять на обычный или на виртуальный метод он указывает…
-1
Виртуальный он или нет — не важно, указатель на метод состоит из this и указателя на функцию-имплементацию метода. Если это обычный метод, то указатель на метод будет вычислен во время компиляции, если виртуальный — скопирован из vtable во время исполнения взятия указателя.
0
И я понял что в статье я пропустил часть предложения, потому вышло неоднозначно как то. Сейчас исправлю, хорошо что вы на это обратили внимание.
+1
С ноткой грусти А вы не пробовали OpenCV под Builder собрать? :)
0
Прошу прощения, не силен в C++, но вот это все нужно чтобы просто реализовать null?
0
Это все нужно чтобы реализовать nullptr на старой версии языка, где его нету.
0
Если вы про null из C# то да, он является аналогом nullptr из C++ (разве что к bool преобразовываться не умеет).
А на счет «просто реализовать» могу сказать что все это нужно чтобы сложно реализовать своими силами то, что должно быть просто реализовано по более новой редакции стандарта языка силами компилятора.
А на счет «просто реализовать» могу сказать что все это нужно чтобы сложно реализовать своими силами то, что должно быть просто реализовано по более новой редакции стандарта языка силами компилятора.
0
Я думал что SFINAE это какая-то продвинутая фича, если есть она то есть и nullptr. Но оказывается я ошибался. Довольно хардкорно выглядит
0
(deleted)
0
Зарегистрируйтесь на Хабре , чтобы оставить комментарий
Как я стандартную библиотеку C++11 писал или почему boost такой страшный. Глава 3