原生 C++ 運算式的限制
這個主題適用於:
版本 |
Visual Basic |
C# |
F# |
C++ |
Web Developer |
---|---|---|---|---|---|
Express |
僅適用原生 |
||||
Pro、Premium 和 Ultimate |
僅適用原生 |
當您將 C/C++ 運算式輸入至偵錯工具視窗時,將會套用下列一般性限制:
存取控制
偵錯工具可存取所有的類別成員,不管其存取控制為何。 您可檢查任何的類別物件成員,包括了基底類別和內嵌的成員物件。
模稜兩可的參考
如果偵錯工具運算式參考到模稜兩可的成員名稱,您必須使用類別名稱來限定它。 例如,如果 CObject 是 CClass 的執行個體,並且它從 AClass 和 BClass 繼承了名為 expense 的成員函式,那麼 CObject.expense 就是模稜兩可的。 您可透過下列方式來解決此語意模糊的問題:
CObject.BClass::expense
運算式評估工具針對成員名稱套用一般的支配規則以解決語意模糊的問題。
匿名命名空間
原生 C++ 運算式評估工具不支援匿名命名空間。 假設,如果您有下列的程式碼:
#include "stdafx.h"
namespace mars
{
namespace
{
int test = 0;
}
}
int main()
{
// Adding a watch on test does not work.
mars::test++;
return 0;
}
在此範例中,監看符號 test 的唯一方法,就是使用裝飾名稱 (Decorated Name):
(int*)?test@?A0xccd06570@mars@@3HA
建構函式、解構函式和轉換
您不能使用要求建構暫存物件的運算式來呼叫 (無論明確或隱含的呼叫) 物件的建構函式 (Constructor) 或解構函式 (Destructor)。 例如,下列的運算式明確地呼叫一個建構函式,並產生錯誤訊息:
Date( 2, 3, 1985 )
您不能呼叫型別轉換函式 (Conversion Function),如果該轉換的目的型別為類別。 這類轉換牽涉到物件的建構。 例如,如果 myFraction 是 CFraction 的執行個體,而其定義了型別轉換函式運算子 FixedPoint,那麼下列的運算式將產生一個錯誤:
(FixedPoint)myFraction
不過,如果轉換的目的型別為內建資料型別,您就可以呼叫型別轉換函式。 如果 CFraction 定義了轉換函式 operator float,下列運算式在偵錯工具中就是合法的:
(float)myFraction
您可以呼叫傳回物件或宣告區域物件 (Local Object) 的函式。
您不能呼叫 new 或 delete 運算子。 下列運算式無法用於偵錯工具內:
new Date(2,3,1985)
繼承
當您使用偵錯工具來顯示具有虛擬 (Virtual) 基底類別的類別物件時,每個繼承路徑的虛擬基底類別成員都會顯示出來,即使這些成員只有一個執行個體被儲存。
虛擬函式呼叫會由運算式評估工具適當地處理。 例如,假設 CEmployee 類別定義一個虛擬函式 computePay,而該虛擬函式又於繼承自 CEmployee 的類別中重新定義。 您可透過指向 CEmployee 的指標來呼叫 computePay,並執行適當的函式:
empPtr->computePay()
您可將衍生類別 (Derived Class) 物件的指標轉換成基底類別物件的指標。 但反方向的轉換則不允許。
內建函式和內嵌函式
偵錯工具運算式不能呼叫內建 (Intrinsic) 或內嵌 (Inline) 函式,除非該函式至少以正常函式的形式出現一次。
數值常數
偵錯工具運算式可以使用八進位、十六進位或十進位格式的整數常數。 根據預設,偵錯工具預期的是十進位常數。 這個設定可以在 [偵錯] 索引標籤的 [一般] 頁面上變更。
您可使用前置或後置符號來代表採用另一種基底的數值。 下表顯示了您可使用的形式。
語法 |
範例 (十進位 100) |
基底 |
---|---|---|
digits |
100 或 64 |
十進位或十六進位,視目前的設定而定。 |
0digits |
0144 |
八進位 (基底 8) |
0ndigits |
0n100 |
十進位 (基底 10) |
0xdigits |
0x64 |
十六進位 (基底 16) |
digitsh |
64h |
十六進位 (基底 16) |
運算子函式
偵錯工具運算式可針對類別,隱含或明確地叫用 (Invoke) 運算子函式。 例如,假設 myFraction 和 yourFraction 為有定義 operator+ 之類別的執行個體。 您可使用下列運算式來顯示這兩個物件的總和:
myFraction + yourFraction
如果運算子函式被定義成 friend 函式,則您可以使用成員函式所採用的相同語法隱含地呼叫它,或是明確地叫用它,如下所示:
operator+( myFraction, yourFraction )
和一般的函式一樣,呼叫運算子函式時所傳入的引數不能要求牽涉到物件建構的轉換。
偵錯工具不支援具有 Const 和非 Const 版本的多載運算子。 具有 const 和非 const 版本的多載運算子經常用於 Standard Template Library 內。
多載化
如果有完全相符的函式存在,或有不需要牽涉到物件建構轉換的函式存在,偵錯工具運算式便可呼叫多載函式。 例如,如果 calc 函式採用 CFraction 物件來做為參數,而 CFraction 類別定義了接受一個整數的單一引數建構函式,那麼下列的運算式將產生一個錯誤:
calc( 23 )
即使有一個合法的轉換可將該整數轉換成 calc 所期待的 CFraction 物件,但是這類轉換牽涉到物件的建立,而偵錯工具並沒有支援。
優先順序
在偵錯工具運算式中,C++ 範圍 (Scope) 運算子 (::) 的優先順序將比它在原始程式碼中來得低。 在 C++ 的原始程式碼中,此運算子具有最高的優先順序。 但在偵錯工具中,其優先順序落在基底和後置運算子 (->、++、--) 和一元 (Unary) 運算子 (!、&、* 及其他) 之間。
符號格式
您輸入的偵錯工具運算式,其所包含的符號採用了與原始程式碼相同的格式,假設符號都放在以完整偵錯資訊 (/Zi 或 /ZI) 編譯的模組內。 如果您輸入一個包含公用符號的運算式,而這些符號位於程式庫或以 /Zd 編譯的模組內,則您必須使用符號的裝飾名稱 (Decorated Name),也就是目的碼 (Object Code) 中使用的格式。 如需詳細資訊,請參閱 /Z7、/Zd、/Zi、/ZI (偵錯資訊格式)。
您可使用 LINK /MAP 選項,取得所有裝飾和未裝飾形式的名稱清單。 如需詳細資訊,請參閱 /MAP (產生對應檔)。
名稱裝飾 (Name Decoration) 是用來強制型別安全連結的機制。 這意味著只有具備完全相符的拼字、大小寫、呼叫慣例 (Calling Convention) 和型別的名稱和參考才會連結在一起。
以 C 呼叫慣例宣告的名稱,不論是隱含或明確地使用 _cdecl 關鍵字,都會以底線 (_) 開頭。 例如,函式 main 可顯示成 _main。 宣告成 _fastcall 的名稱則以 @ 符號開頭。
對於 C++ 而言,除了呼叫慣例外,還會將符號型別編入裝飾名稱。 此種形式的名稱可能會很長,並且很難閱讀。 名稱至少會以一個問號 (?) 開頭。 對於 C++ 函式而言,裝飾將包含函式範圍、函式參數的型別以及函式的傳回型別 (Return Type)。
型別轉換
如果轉換為某個型別,則該型別必須是偵錯工具已知的型別。 您的程式中必須有另一個該型別的物件。 使用 typedef 陳述式 (Statement) 所建立的型別不受支援。