Почему в C++ нет отражения?

Это несколько странный вопрос. Мои цели - понять решение о языковом дизайне и определить возможности отражения в C++.

  1. Почему комитет по языку C++ не пошел на реализацию отражения на языке? Слишком сложно рефлексировать на языке, который не работает на виртуальной машине (например, java)?

  2. Если бы нужно было реализовать отражение для C++, какие были бы проблемы?

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
349
0
56 388
13

Ответы 13

Отражение требует, чтобы некоторые метаданные о типах были где-то храниться, чтобы их можно было запросить. Поскольку C++ компилируется в собственный машинный код и претерпевает серьезные изменения из-за оптимизации, высокоуровневое представление приложения в значительной степени теряется в процессе компиляции, следовательно, невозможно будет запросить их во время выполнения. Java и .NET используют представление очень высокого уровня в двоичном коде виртуальных машин, что делает возможным такой уровень отражения. Однако в некоторых реализациях C++ есть нечто, называемое информацией о типе времени выполнения (RTTI), которое можно рассматривать как урезанную версию отражения.

RTTI соответствует стандарту C++.

Daniel Earwicker 12.12.2008 10:27

Но не все реализации C++ являются стандартными. Я видел реализации, которые не поддерживают RTTI.

mmx 14.12.2008 12:44

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

Michael Kohne 06.11.2009 23:12

Отражение может быть и было реализовано в C++ раньше.

Это не встроенная функция C++, потому что у нее высокая стоимость (память и скорость), которые не должны устанавливаться языком по умолчанию - язык ориентирован на «максимальную производительность по умолчанию».

Так как вы не должны платить за то, что вам не нужно, и, как вы сами говорите, в редакторах этого нужно больше, чем в других приложениях, то это должно быть реализовано только там, где вам это нужно, а не «принудительно» для всего кода ( вам не нужно отражать все данные, с которыми вы будете работать в редакторе или другом аналогичном приложении).

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

gbjbaanb 11.12.2008 16:06

Вы правы, я даже не задумывался о проблеме с выставлением кода :)

Klaim 11.12.2008 16:38

Причина, по которой C++ не имеет отражения, заключается в том, что это потребовало бы от компиляторов добавления символьной информации в объектные файлы, например, какие члены имеет тип класса, информацию о членах, о функциях и всем остальном. По сути, это сделает включаемые файлы бесполезными, поскольку информация, отправляемая объявлениями, затем будет считана из этих объектных файлов (а затем модулей). В C++ определение типа может встречаться в программе несколько раз за счет включения соответствующих заголовков (при условии, что все эти определения одинаковы), поэтому нужно будет решить, куда поместить информацию об этом типе, так же как назвать один сложность здесь. Еще одна сильная сторона - агрессивная оптимизация, выполняемая компилятором C++, который может оптимизировать десятки экземпляров шаблонов классов. Это возможно, но, поскольку C++ совместим с C, это стало бы неудобной комбинацией.

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

Rob Kennedy 11.12.2008 16:39

Проблема в том, что ваша информация об отражении может быть недействительной. Если компилятор удаляет 80% определений вашего класса, что скажут ваши метаданные отражения? В C# и Java язык гарантирует, что если вы определите класс, он останется определенным. C++ позволяет компилятору оптимизировать его.

jalf 11.12.2008 16:47

@Rob, оптимизации - это еще один момент, не связанный с усложнением нескольких классов. См. Комментарий @jalf (и его ответ), чтобы узнать, что я имел в виду.

Johannes Schaub - litb 31.08.2009 16:25

Если я создаю экземпляр reflection <T>, не выбрасывайте никакую информацию T. Это не кажется неразрешимой проблемой.

Joseph Garvin 28.11.2009 09:51

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

Также Дизайн и развитие C++ от Страуструпа

James Hopkin 11.12.2008 19:26

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

Компилятор C++ ничего не хранит (ну, игнорируя RTTI), поэтому вы не получите отражения в языка. (Компиляторы Java и C# хранят только имена классов, методов и возвращаемые типы, поэтому вы получаете немного данных отражения, но не можете проверять выражения или структуру программы, а это означает, что даже в этих языках с поддержкой отражения информация, которую вы можете получить, довольно скудна, и, следовательно, вы действительно не можете провести большой анализ).

Но вы можете изменить язык вне и получить полную возможность отражения. Ответ на другое обсуждение переполнения стека на отражение в C обсуждает это.

Я считаю, что отражение в C++ крайне важно, если C++ будет использоваться в качестве языка для доступа к базам данных, обработки веб-сеансов / http и разработки графического интерфейса. Отсутствие отражения предотвращает использование ORM (таких как Hibernate или LINQ), синтаксических анализаторов XML и JSON, которые создают экземпляры классов, сериализации данных и многих других вещей (где изначально для создания экземпляра класса должны использоваться данные без типа).

Можно использовать переключатель времени компиляции, доступный разработчику программного обеспечения во время процесса сборки. чтобы устранить эту озабоченность «вы платите за то, что используете».

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

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

Для меня это проблема №1 (а примитивы с простыми потоками - это проблема №2).

Кто сказал, что C++ является можно использовать в качестве языка для доступа к БД, управления веб-сессиями или графического интерфейса разработчика? Есть много гораздо лучших языков, которые можно использовать для такого рода вещей. И переключатель времени компиляции не решит проблему. Обычно решение о включении или отключении отражения не принимается отдельно для каждого файла. Это могло бы сработать, если бы его можно было включить для отдельных типов. Если программист может указать с помощью атрибута или подобного при определении типа, должны ли создаваться метаданные отражения для него. Но глобальный переключатель? Вы испортили бы 90% информации, чтобы сделать ее проще на 10%.

jalf 11.09.2009 19:36

Затем, если мне нужна кроссплатформенная программа с доступом к графическому интерфейсу, что мне следует использовать? Несгибаемый java-качели? Окна только C#? Но правда следует сказать, и правда в том, что есть много программ, которые скомпилированы в исполняемый код и предлагают графический интерфейс и доступ к базам данных, поэтому они должны использовать некоторую базу данных и поддержку графического интерфейса ... И это не так. t с помощью QT. (он должен был называться MT (набор инструментов для монстров))

Coyote21 31.05.2011 00:15

@ Coyote21: C# уже много лет не предназначен только для Windows. (Хотя я не фанат Mono, он работает достаточно хорошо для большинства вещей.) Swing - не единственный инструментарий GUI для Java. По правде говоря, любой из них будет лучшим выбором, если вы хотите кроссплатформенность. С ++ почти всегда будет иметь части, специфичные для платформы, здесь или там, если вы делаете что-то нетривиальное.

cHao 17.04.2012 18:56

Нет причин, по которым вам нужна рефлексия для ORM. Вы можете добиться всего этого с помощью шаблонов. Существует множество фреймворков, которые предоставляют ORM для C++.

MrFox 06.07.2012 23:46

Как это на самом деле отвечает на вопрос?

Toby Speight 26.03.2021 16:22

Если бы C++ мог иметь:

  • данные членов класса для имен переменных, типов переменных и модификатора const
  • итератор аргументов функции (только позиция вместо имени)
  • данные членов класса для имен функций, типа возвращаемого значения и модификатора const
  • список родительских классов (в том же порядке, что и определено)
  • данные для членов шаблона и родительских классов; расширенный шаблон (это означает, что для API отражения будет доступен фактический тип, а не «информация о шаблоне о том, как туда добраться»)

Этого было бы достаточно, чтобы создать очень простые в использовании библиотеки, необходимые для безтиповой обработки данных, которая так распространена в современных веб-приложениях и приложениях баз данных. (все ормы, механизмы обмена сообщениями, парсеры xml / json, сериализация данных и т. д.).

Например, основная информация, поддерживаемая макросом Q_PROPERTY (часть Qt Framework) http://qt.nokia.com/doc/4.5/properties.html расширен, чтобы охватить методы класса и e) - было бы чрезвычайно полезно для C++ и для сообщества разработчиков программного обеспечения в целом.

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

@Vlad: Да, если добавить в язык функции, поддерживающие отражение, вы получите отражение в языке. Это может произойти только в том случае, если языковой комитет примет это постановление, а я думаю, что они этого не сделали с 2011 года, и я сомневаюсь, что до 2020 года нашей эры будет выпущен еще один стандарт C++. Итак, хорошая мысль. Между тем, если вы хотите добиться прогресса, вам, вероятно, придется выйти за рамки C++.

Ira Baxter 19.06.2011 09:51

По словам Алистера Кокберна, подтипирование не может быть гарантировано в рефлексивной среде.

Рефлексия более актуальна для систем скрытой печати. В C++ вы знаете, какой у вас тип, и знаете, что с ним делать.

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

supercat 05.03.2013 00:42

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

C++ - это, по сути, очень и очень сложный ассемблер макросов. Это НЕ (в традиционном смысле) язык высокого уровня, такой как C#, Java, Objective-C, Smalltalk и т. д.

Хорошо иметь разные инструменты для разных работ. Если у нас есть только молотки, все будет похоже на гвозди и т. д. Наличие языков сценариев полезно для некоторых работ, а рефлексивные OO-языки (Java, Obj-C, C#) полезны для другого класса работ, и супер -эффективные простые языки, близкие к машинным, полезны для еще одного класса задач (C++, C, Assembler).

C++ делает потрясающую работу по расширению технологии Assembler до невероятных уровней управления сложностью и абстракций, чтобы сделать программирование более масштабных и сложных задач гораздо более доступным для людей. Но это не обязательно язык, который лучше всего подходит для тех, кто подходит к своей проблеме с точки зрения строго высокого уровня (Lisp, Smalltalk, Java, C#). Если вам нужен язык с этими функциями, чтобы наилучшим образом реализовать решение ваших проблем, поблагодарите тех, кто создал такие языки для всех нас!

Но C++ предназначен для тех, кому по каким-либо причинам необходимо иметь сильную корреляцию между их кодом и работой базовой машины. Будь то эффективность, программирование драйверов устройств, взаимодействие с низкоуровневыми службами ОС или что-то еще, C++ лучше подходит для этих задач.

C#, Java, Objective-C - все требуют гораздо более обширной и богатой системы времени выполнения для поддержки их выполнения. Эта среда выполнения должна быть доставлена ​​в рассматриваемую систему - предварительно установлена ​​для поддержки работы вашего программного обеспечения. И этот уровень необходимо поддерживать для различных целевых систем, настраивая НЕКОТОРЫЙ ДРУГОЙ ЯЗЫК, чтобы он работал на этой платформе. И этот промежуточный уровень - этот адаптивный уровень между ОС хоста и вашим кодом - среда выполнения почти всегда написана на таком языке, как C или C++, где эффективность - номер 1, где предсказуемо точное взаимодействие между программным обеспечением и оборудованием может быть хорошо понимал и манипулировал с максимальной выгодой.

Мне нравится Smalltalk, Objective-C и богатая среда выполнения с отражением, метаданными, сборкой мусора и т. д. Чтобы воспользоваться этими возможностями, можно написать потрясающий код! Но это просто более высокий уровень в стеке, уровень, который должен лежать на более низких уровнях, который, в конечном итоге, должен лежать на ОС и оборудовании. И нам всегда будет нужен язык, который лучше всего подходит для создания этого слоя: C++ / C / Assembler.

Приложение: C++ 11/14 продолжает расширять возможности C++ для поддержки абстракций и систем более высокого уровня. Распределение потоков, синхронизация, точные модели памяти, более точные определения абстрактных машин позволяют разработчикам C++ достигать многих высокоуровневых абстракций, которые некоторые из этих языков высокого уровня использовали для монопольной области, продолжая при этом обеспечивать близкие к - металлические характеристики и отличная предсказуемость (т.е. минимальное время работы подсистем). Возможно, в будущей версии C++ для тех, кто этого хочет, средства отражения будут выборочно включены - или, возможно, библиотека будет предоставлять такие службы времени выполнения (может быть, они есть сейчас или они только начинаются?).

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

Richard J. Ross III 08.05.2013 03:01

Это различие без разницы. Какая разница, если в конечном итоге подсистема времени выполнения, которую использует Objective-C, на самом деле написана не на Objective-C, а, скорее, на C?

Mordachai 09.05.2013 01:32

Objective-C является C, и в этом суть. Любая программа на C является допустимой для Objective-C, поэтому ее система времени выполнения фактически компилируется на ее собственном языке.

Richard J. Ross III 09.05.2013 04:08

Нет, вы не можете написать программу Objective-C, которая компилируется с помощью компилятора C. Это разные языки. Вы не можете создавать объекты Obj-C, вы не можете использовать какие-либо службы отражения времени выполнения в C и т. д. Просто потому, что Objective-C расширяет C, не делает их одним языком и не устраняет необходимость в подсистеме времени выполнения для управления временем жизни объекта. и система типовых запросов, среди других функций Objective-C.

Mordachai 09.05.2013 16:34

Мне жаль; но если вы правильно свяжете его, вы можете скомпилировать программу objective-c на C, на самом деле я сделал это здесь: stackoverflow.com/a/10290255/427309. Все ваше заявление выше ложно. Среда выполнения полностью доступна через C, и это одна из вещей, которая делает ее таким мощным динамическим языком.

Richard J. Ross III 09.05.2013 16:43

Право ... через C. C. Требуется. Для Objective-C существует среда выполнения. Эта среда выполнения управляет отражением типов, передачей сообщений, объектами классов, управлением памятью и т. д. Я не уверен, что вы зацикливаетесь или считаете неправильным. Без среды выполнения Objective-C не существовал бы. В C++ нет среды выполнения (нет отражения динамического типа, нет подсистемы управления памятью, нет динамической привязки вызовов за пределами v-таблиц). Это сильное различие, и это чистая правда.

Mordachai 09.05.2013 18:59

Незначительный педантичный момент: у C++ и C также есть система времени выполнения. Тот факт, что вы можете встроить среду выполнения в двоичный файл или что они обычно меньше, чем CLR / JVM, ортогонален их существованию (привет, msvcrtXXX.dll!). Вы должны отказаться от таких вещей, как malloc, чтобы получить настоящие бинарные файлы с голыми костями без времени выполнения (например: см. Поддержку Rust libcore для написания загрузчиков и ядер, где вы предоставляете пару базовых функций начальной загрузки, таких как malloc, или просто полностью избегаете выделения кучи)

russbishop 27.07.2014 06:46

Педантическое исправление: msvcrt предоставляет «библиотеку времени выполнения C», но сама по себе не является ядром языка. И в какой-то момент вы доходите до градусов: где провести черту между средой выполнения и ее отсутствием? Я считаю, что в C нет среды выполнения - нет сборки мусора, никаких других потоков, управляющих чем-либо, никаких автоматических функций. Нет системы типов времени выполнения. Ничего, кроме интерфейсов типа malloc, которые могут быть реализованы как фасад ОС, и, следовательно, если вы не рассматриваете саму ОС как «языковую среду выполнения», то C не имеет среды выполнения вообще.

Mordachai 07.08.2014 00:15

на самом деле вы можете: операционная система предоставляет mmap, и в этом смысле она предоставляет распределитель для языков. он также иногда поддерживает sbrk и фиксацию страниц стека, сигнализацию доступа к странице с защитой стека, сигнализацию ошибок сегментации, sigbus, создание канала, создание потока, создание фильтра, поддержку переключателей контекста, абстракцию файловой системы, каналы ... для меня это огромное время выполнения.

v.oddou 01.09.2014 10:56

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

Mordachai 16.03.2015 20:34

«Среда выполнения C» - это просто динамическая библиотека, содержащая код стандартной библиотеки C. То же самое для «среды выполнения C++». Это сильно отличается от системы времени выполнения, такой как Objective-C. Кроме того ... хотя я полагаю, что вы могли бы технически использовать среду выполнения Objective-C на C, это все еще просто программа C, которая использует среду выполнения Objective-C - вы не можете скомпилировать настоящую программу Objective-C на C.

celticminstrel 24.07.2015 18:23

C++ 11, имеющий модель памяти + атомику, делает его более похожим на портативный ассемблер. Это не высокоуровневые вещи, это вещи уровня низкий, для которых C++ ранее не имел переносимой поддержки. Но количество UB в C++, если вы делаете что-то не так, делает его очень непохожим на языки на основе виртуальных машин, такие как Java, а также на любой конкретный язык ассемблера. например подписанное переполнение - это полностью UB в исходном коде C++ и компилятор может оптимизировать на основе этого факта, даже если компилируется, скажем, для x86, но в asm почти на всех платформах он просто оборачивается. Современный C++ очень далек от переносимого языка ассемблера.

Peter Cordes 14.08.2018 13:20

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

N3340 предлагает расширенные указатели как способ внедрения отражения в C++. Среди прочего, он решает проблему неоплаты за функцию, если вы ее не используете.

Отражение может быть необязательным, как директива препроцессора. Что-то вроде

#pragma enable reflection

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

Как это отвечает на фактически заданный вопрос?

Toby Speight 26.03.2021 16:19

Это в основном потому, что это «дополнительная опция». Многие люди предпочитают C++ таким языкам, как Java и C#, чтобы иметь больший контроль над выводом компилятора, например. меньшая и / или более быстрая программа.

Если вы решите добавить отражение, есть доступны различные решения.

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

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

ATL_DEV 28.02.2021 02:49

Другие вопросы по теме