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

Вы правы, но вы хотите merge, а не concat. Попробуйте следующее:

DF = pd.merge(df1,df2,on=['Genre','City'])
DF.Groupby([['Genre','City']]).sum().unstack().plot(kind = 'bar')
327
задан amit 11 December 2008 в 12:52
поделиться

11 ответов

Существует несколько проблем с отражением в C++.

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

  • Вы не платите за то, что Вы не используете. Это - один из должен против базовых основных положений дизайна, лежащих в основе C++. Почему мой код должен нести вокруг метаданных, если мне никогда, возможно, не понадобится он? Кроме того, добавление метаданных может запретить компилятору оптимизация. Почему я должен оплатить ту стоимость в своем коде, если мне никогда, возможно, не понадобятся те метаданные?

  • Который приводит нас к другой большой точке: C++ делает очень немного гарантий о скомпилированном коде. Компилятору позволяют сделать в значительной степени что-либо, что он любит, пока получающаяся функциональность - то, что ожидается. Например, Ваши классы не требуются, чтобы на самом деле быть там. Компилятор может оптимизировать их далеко, встроить все, что они делают, и он часто делает просто это, потому что даже простой код шаблона имеет тенденцию создавать довольно много шаблонных инстанцирований. Библиотека стандарта C++ полагается на эту агрессивную оптимизацию. Функторы только производительны, если издержки инстанцирования и разрушения объекта могут быть оптимизированы далеко. operator[] на векторе только сопоставимо с необработанной индексацией массива в производительности, потому что весь оператор может быть встроен и таким образом удален полностью из скомпилированного кода. C# и Java делают много гарантий о выводе компилятора. Если я определю класс в C#, то тот класс будет существовать в получающемся блоке. Даже если я никогда не использую его. Даже если все вызовы к его функциям членства могли бы быть встроены. Класс должен быть там, так, чтобы отражение могло найти его. Часть этого облегчена компиляцией C# в байт-код, что означает, что JIT-компилятор может удалить определения классов и подставляемые функции, если этому нравится, даже если первоначальный компилятор C# не может. В C++ у Вас только есть один компилятор, и он должен произвести эффективный код. Если бы Вам разрешили осмотреть метаданные исполняемого файла C++, то Вы ожидали бы видеть каждый класс, который они определили, что означает, что компилятор должен был бы сохранить все определенные классы, даже если они не необходимы.

  • И затем существуют шаблоны. Шаблоны в C++ - ничто как дженерики на других языках. Каждое шаблонное инстанцирование создает новый тип. std::vector<int> абсолютно отдельный класс от std::vector<float>. Это составляет в целом много различных типов во всей программе. Что должно видеть наше отражение? Шаблон std::vector? Но как может он, так как это - конструкция исходного кода, которая не имеет никакого значения во времени выполнения? Это должно было бы видеть отдельные классы std::vector<int> и std::vector<float>. И std::vector<int>::iterator и std::vector<float>::iterator, то же для const_iterator и так далее. И после того как Вы ступаете в шаблонное метапрограммирование, Вы быстро заканчиваете тем, что инстанцировали сотен шаблонов, все из которых встраиваются и удалили снова компилятором. У них нет значения, за исключением части метапрограммы времени компиляции. Должны все эти сотни классов быть видимыми к отражению? Они имели бы к, потому что иначе наше отражение будет бесполезно, если оно даже не гарантирует, что классы, которые я определил, на самом деле будут там. И проблема стороны состоит в том, что шаблонный класс не существует, пока он не инстанцируют. Вообразите программу, которая использует std::vector<int>. Если наша отражательная система может видеть std::vector<int>::iterator? С одной стороны Вы, конечно, ожидали бы так. Это - важный класс, и это определяется с точки зрения std::vector<int>, который действительно существует в метаданных. С другой стороны, если программа никогда на самом деле использует этот шаблон класса итератора, его тип никогда не будут инстанцировать, и таким образом, компилятор не будет генерировать класс во-первых. И слишком поздно для создания его во времени выполнения, так как это требует доступа к исходному коду.

  • И наконец, отражение не вполне так же жизненно важно в C++, как это находится в C#. Причина снова, шаблонное метапрограммирование. Это не может решить все, но для многих случаев, где Вы иначе обратились бы к отражению, возможно записать метапрограмму, которая делает то же самое во время компиляции. boost::type_traits простой пример. Вы хотите знать о типе T? Проверьте type_traits. В C# необходимо было бы ловить рыбу вокруг после его типа с помощью отражения. Отражение все еще было бы полезно для некоторых вещей (основное использование I видит, который не может легко заменить метапрограммирование, для автоматически сгенерированного кода сериализации), но это несло бы некоторые значительные затраты для C++, и это просто не необходимо так же часто, как это находится на других языках.

Править: В ответ на комментарии:

cdleary: Да, отладочные символы делают что-то подобное, в этом они хранят метаданные о типах, используемых в исполняемом файле. Но они также страдают от проблем, которые я описал. Если Вы когда-либо пытались отладить сборку конечных версий, Вы будете знать то, что я имею в виду. Существуют большие логические разрывы, где Вы создали класс в исходном коде, который стал встроенным далеко в заключительном коде. Если бы необходимо было использовать отражение для чего-либо полезного, то Вам было бы нужно оно, чтобы быть более надежными и последовательными. Как это, типы исчезли бы и исчезли бы почти каждый раз, когда Вы компилируете. Вы изменяете крошечную небольшую деталь, и компилятор решает измениться, какие типы встраиваются и которые не делают как ответ. Как Вы извлекаете что-либо полезное из этого, когда Вам даже не гарантируют это, самые соответствующие типы будут представлены в Ваших метаданных? Тип, который Вы искали, возможно, был там в последней сборке, но теперь это пошло. И завтра, кто-то зарегистрируется в небольшом невинном изменении в небольшой невинной функции, которая делает тип просто достаточно большим, что он не будет полностью встроен, таким образом, он вернется снова. Это все еще полезно для отладочных символов, но не намного больше, чем это. Я не хотел бы пытаться сгенерировать код сериализации для класса в соответствии с теми условиями.

Evan Teran: Конечно, эти вопросы могли быть решены. Но это отступает к моей точке № 1. Потребовалась бы большая работа, и комитет C++ имеет много вещей, которые они чувствуют, более важно. Разве преимущество получения является некоторым ограниченным отражением (и оно было бы ограничено) в C++, достаточно действительно большом для выравнивания по ширине фокусировки на этом за счет других функций? Существует ли действительно огромное преимущество в добавлении опций базовый язык, который может уже (главным образом) быть сделан через библиотеки и препроцессоры как QT? Возможно, но потребность является намного менее срочной, чем если бы такие библиотеки не существовали. Для Ваших определенных предложений, хотя, я верю, запрещение его на шаблонах сделало бы его абсолютно бесполезным. Вы не могли бы использовать отражение о стандартной библиотеке, например. Какое отражение не позволило бы Вам видеть a std::vector? Шаблоны являются огромной частью C++. Функция, которая не работает над шаблонами, в основном бесполезна.

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

Но как я сказал, существует предложение по изменениям в модели компиляции, добавляя автономные модули, храня метаданные для избранных типов, позволяя другим модулям сослаться на них, не имея необходимость смешивать с #includes. Это - хорошее начало, и честно говоря, я удивлен, что стандартный комитет только вывел предложение по тому, чтобы быть слишком большим изменением. Таким образом, возможно, за 5-10 лет?:)

612
ответ дан Ziezi 23 November 2019 в 00:51
поделиться

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

38
ответ дан Mehrdad Afshari 4 November 2019 в 10:27
поделиться

Если Вы действительно хотите понять, что проектные решения, окружающие C++, находят копию Аннотируемый Справочник C++ Ellis и Stroustrup. Это не актуально с последним стандартом, но это проходит исходный стандарт и объясняет, как вещи работают и часто, как они получили тот путь.

11
ответ дан Michael Kohne 4 November 2019 в 10:27
поделиться

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

Это не собственная функция C++, потому что это имеет большую стоимость (память и скорость), что should'nt быть установленным по умолчанию языком - язык является "максимальной производительностью, по умолчанию" ориентированной.

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

8
ответ дан Klaim 4 November 2019 в 10:27
поделиться

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

6
ответ дан Johannes Schaub - litb 4 November 2019 в 10:27
поделиться
1
ответ дан amit 23 November 2019 в 00:51
поделиться

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

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

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

9
ответ дан 23 November 2019 в 00:51
поделиться

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

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

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

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

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

0
ответ дан 23 November 2019 в 00:51
поделиться

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

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

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

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

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

2
ответ дан 23 November 2019 в 00:51
поделиться

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

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

2
ответ дан 23 November 2019 в 00:51
поделиться

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

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 ++ для тех, кто этого хочет - или, возможно, библиотека будет предоставлять такие службы времени выполнения (возможно, они есть сейчас, или начало одного в разгоне?).

17
ответ дан 23 November 2019 в 00:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: