У C ++ уже есть какое-то отражение? - PullRequest
6 голосов
/ 11 июня 2011

Рассмотрим этот пример:

struct Nobody_Expects_The_Spanish_Inquisition{};

int main(){
    throw Nobody_Expects_The_Spanish_Inquisition();
}

Вывод, показанный на Ideone :

прекращение вызова после выброса экземпляра Nobody_Expected_The_Spanish_Inquisition '

Аналогичные выходные данные для Windows:

Необработанное исключение при 0x760fb727 в Test.exe: исключение Microsoft C ++: Nobody_Expected_The_Spanish_Inquisition в ячейке памяти 0x001ffea3 ..

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

Может ли это рассматриваться как некое подобиеотражения?Или это зависит от компилятора / ОС, если имя исключения действительно может быть отображено?

Ответы [ 5 ]

7 голосов
/ 11 июня 2011

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

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

3 голосов
/ 11 июня 2011

Нет, это не отражение в каком-либо значимом качестве, просто символы отладки.

2 голосов
/ 11 июня 2011

Когда исключение выходит за пределы main, вызывается std::terminate, что, в свою очередь, вызывает установленный обработчик завершения.Если в программе не установлен обработчик завершения, вызывается обработчик завершения по умолчанию.Требование only для этого обработчика завершения по умолчанию состоит в том, что он вызывает std::abort.Это означает, что реализация может свободно печатать полезное сообщение перед вызовом std::abort, что, по-видимому, здесь имеет место.

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

0 голосов
/ 11 июня 2011

«Отражение» производится с использованием RTTI. Ничего особенного, только название типа.

0 голосов
/ 11 июня 2011

Эта программа:

#include <typeinfo>
#include <iostream>

struct Nobody_Expects_The_Spanish_Inquisition {
};

namespace junk {
struct I_didnt_expect_a_kind_of_spanish_inquisition
   : public Nobody_Expects_The_Spanish_Inquisition
{
};
}

int main(int argc, const char *argv[])
{
   using ::std::type_info;
   using ::std::cout;

   Nobody_Expects_The_Spanish_Inquisition foo;
   junk::I_didnt_expect_a_kind_of_spanish_inquisition bar;
   const type_info &fooinfo = typeid(foo);
   const type_info &barinfo = typeid(bar);
   cout << "The type of foo is <" << fooinfo.name() << ">\n";
   cout << "The type of bar is <" << barinfo.name() << ">\n";
   return 0;
}

имеет такой вывод:

$ ./foo 
The type of foo is <38Nobody_Expects_The_Spanish_Inquisition>
The type of bar is <N4junk44I_didnt_expect_a_kind_of_spanish_inquisitionE>

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

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

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

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

Таким образом, RTTI не требуется для реализации функции, которую вы отмечаете. Но RTTI - очень элементарная форма отражения, и ее можно использовать для реализации этой функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...