Поделиться через


Ограничения на выражения C++ в машинном коде

Этот раздел применим к:

Выпуск

Visual Basic

C#

F#

C++

Web Developer

Express

Тема не применяется Тема не применяется Тема не применяется

Только машинные коды

Тема не применяется

Pro, Premium и Ultimate

Тема не применяется Тема не применяется Тема не применяется

Только машинные коды

Тема не применяется

При вводе выражения на языке C/C++ в окне отладчика применимы следующие общие ограничения.

Управление доступом

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

Неоднозначные ссылки

Если в выражении отладчика указано неоднозначное имя элемента, его следует уточнить с помощью имени класса. Например если CObject является экземпляром класса CClass, который наследует функции элемента с именем expense из AClass и BClass, то CObject.expense будет неоднозначным. Такую неоднозначность можно устранить путем следующего уточнения:

CObject.BClass::expense

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

Анонимные пространства имен

В машинном выражении C++ средство оценки выражений не поддерживает анонимные пространства имен. Предположим, например, имеется следующий XML-код:

#include "stdafx.h"

namespace mars

{

namespace

{

int test = 0;

}

}

int main()

{

// Adding a watch on test does not work.

mars::test++;

return 0;

}

Единственный способ наблюдения символа test в этом примере состоит в использовании внутреннего имени:

(int*)?test@?A0xccd06570@mars@@3HA

Конструкторы, Деструкторы и Преобразования

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

Date( 2, 3, 1985 )

Функция преобразования не может быть вызвана, если результатом преобразования должен быть класс. Такое преобразование включает конструирование объекта. Например, если myFraction — экземпляр класса CFraction, в котором определен оператор функции преобразования FixedPoint, то следующее выражение вызовет ошибку:

(FixedPoint)myFraction

Однако вызов функции преобразования допускается, если результат преобразования — встроенный тип. Если CFraction определяет функцию преобразования operator float, то следующее выражение в отладчике является правильным:

(float)myFraction

Можно вызывать функции, возвращающие объект или объявляющие локальные объекты.

Вы не можете вызвать оператор new или delete. Следующее выражение не будет действовать в отладчике:

new Date(2,3,1985)

Наследование

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

Вызовы виртуальной функции правильно обрабатываются средством оценки выражений. Например, предположим, что класс CEmployee определяет виртуальную функцию computePay, которая переопределена в классе, наследующем из CEmployee. Можно вызвать computePay через указатель на CEmployee и иметь соответствующую выполняющуюся функцию:

empPtr->computePay()

Указатель на объект производного класса можно привести к указателю на объект базового класса. Обратное приведение недопустимо.

Подставляемые и встроенные функции

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

Числовые константы

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

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

Синтаксис

Пример (десятичное число 100)

Основание

цифры

100 или 64

Десятичный или шестнадцатеричный, в зависимости от текущей настройки.

0цифры

0144

8 (основание 8)

0nцифры

0n100

10 (основание 10)

0xцифры

0x64

16 (основание 16)

цифрыh

64h

16 (основание 16)

Операторные функции

Выражение отладчика может явным или неявным образом вызывать операторные функции для класса. Например предположим, что myFraction и yourFraction являются экземплярами класса, определяющие operator+. С помощью следующего выражения можно получить сумму этих двух объектов:

myFraction + yourFraction

Если операторная функция определена как дружественная, то ее можно вызвать неявно с помощью такого же синтаксиса, как и в случае функции-члена, или же вызвать ее явным способом, как показано в следующем примере:

operator+( myFraction, yourFraction )

Операторные функции, как и обычные функции, не могут вызываться с аргументами, требующими преобразования с конструированием объекта.

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

Перегрузка

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

calc( 23 )

Даже если существует допустимое преобразование целого числа в объект CFraction, который ожидает calc, что подобное преобразование потребует создания объекта, и поэтому не поддерживается.

Приоритет

Оператор области видимости C++ (::) в выражениях отладчика имеет более низкий приоритет применения, чем в исходном коде. В исходном коде на языке C++ этот оператор имеет наивысший приоритет применения. В отладчике его приоритет применения выше, чем у базовых и постфиксных операторов (->, ++, --), но ниже, чем у унарных операторов (!, &, * и др.).

Форматы символов

Выражение отладчика с символами вводится в том же виде, который используется в исходном коде, при условии что символы находятся в модуле, откомпилированном в режиме вывода полных отладочных данных (/Zi или /ZI).. Если вводится выражение с открытыми символами, которые находятся в библиотеках или в модулях, откомпилированных с параметром /Zd, необходимо использовать внутреннее имя символа (форму, используемую в объектном коде). Дополнительные сведения см. в разделе /Z7, /Zd, /Zi, /ZI (формат отладочной информации).

Список всех имен в декорированной и недекорированной формах можно получить с помощью параметра LINK /MAP. Дополнительные сведения см. /MAP (Создание Map-файла).

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

Имена, объявленные с использованием соглашения о вызовах языка C (неявным образом или явным с помощью зарезервированного слова _cdecl), начинаются с знака подчеркивания (_). Например функция main может отображаться как _main. Имена, объявленные как _fastcall, начинаются с символа @.

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

Тип приведения

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

См. также

Другие ресурсы

Выражения языка C++ в машинном коде