共用方式為


編譯器錯誤 C2065

' identifier ' : 未宣告的識別碼

編譯器找不到識別碼的宣告。 此錯誤有許多可能的原因。 C2065 最常見的原因是識別碼尚未宣告、識別碼拼錯、宣告識別碼的標頭未包含在檔案中,或識別碼遺漏範圍限定詞,例如, cout 而不是 std::cout 。 如需 C++ 中宣告的詳細資訊,請參閱 宣告和定義 (C++)。

以下是更詳細的一些常見問題和解決方案。

識別碼未宣告

如果識別碼是變數或函式名稱,您必須先宣告它,才能使用它。 函式宣告也必須包含其參數的類型,才能使用函式。 如果使用 宣告 auto 變數,編譯器必須能夠從其初始化運算式推斷型別。

如果識別碼是類別或結構的成員,或是在命名空間中宣告,則必須在結構、類別或命名空間範圍之外使用時,由類別或結構名稱或命名空間名稱限定。 或者,命名空間必須由 using 之類的 using namespace std; 指示詞帶入範圍,或者成員名稱必須由 宣告帶入範圍 using ,例如 using std::string; 。 否則,未限定的名稱會被視為目前範圍內未宣告的識別碼。

如果識別碼是使用者定義類型的標籤,例如 classstruct 或 ,則必須先宣告標記的類型,才能使用。 例如,宣告 struct SomeStruct { /*...*/ }; 必須存在,才能在程式碼中宣告變數 SomeStruct myStruct;

如果識別碼是類型別名,則型別必須由宣告宣告 usingtypedef 才能使用。 例如,您必須先宣告 using my_flags = std::ios_base::fmtflags; ,才能使用 my_flags 做為 的 std::ios_base::fmtflags 型別別名。

範例:拼錯識別碼

當識別碼名稱拼錯,或識別碼使用錯誤的大寫和小寫字母時,通常會發生此錯誤。 宣告中的名稱必須完全符合您使用的名稱。

// C2065_spell.cpp
// compile with: cl /EHsc C2065_spell.cpp
#include <iostream>
using namespace std;
int main() {
    int someIdentifier = 42;
    cout << "Some Identifier: " << SomeIdentifier << endl;
    // C2065: 'SomeIdentifier': undeclared identifier
    // To fix, correct the spelling:
    // cout << "Some Identifier: " << someIdentifier << endl;
}

範例:使用未限定範圍的識別碼

如果您的識別碼範圍不正確,就可能發生此錯誤。 如果您在使用 cout 時看到 C2065,範圍問題就是原因。 當 C++ 標準程式庫函式和運算子未依命名空間完整限定,或您尚未使用 using 指示詞將命名空間帶入 std 目前範圍時,編譯器找不到它們。 若要修正此問題,您必須完整限定識別碼名稱,或使用 指示詞指定命名空間 using

此範例無法編譯,因為 coutendl 是在 命名空間中 std 定義:

// C2065_scope.cpp
// compile with: cl /EHsc C2065_scope.cpp
#include <iostream>
// using namespace std;   // Uncomment this line to fix

int main() {
    cout << "Hello" << endl;   // C2065 'cout': undeclared identifier
                               // C2065 'endl': undeclared identifier
    // Or try the following line instead
    std::cout << "Hello" << std::endl;
}

在 、 structenum class 類型內 class 宣告的識別碼,當您在該範圍之外使用這些識別碼時,也必須以其封入範圍的名稱來限定。

範例:先行編譯標頭不是第一個

如果您在先行編譯標頭檔之前 #include 放置任何預處理器指示詞,例如 #include#define#pragma ,就會發生此錯誤。 如果您的原始程式檔使用先行編譯標頭檔(也就是使用編譯器選項進行編譯 /Yu ),則會忽略先行編譯標頭檔之前的所有預處理器指示詞。

此範例無法編譯,因為 coutendl 定義于 標頭中 <iostream> ,因為其包含在先行編譯標頭檔之前,所以會忽略它。 若要建置此範例,請建立這三個檔案,然後編譯 pch.h (Visual Studio 的某些版本使用 stdafx.cpp ),然後編譯 C2065_pch.cpp

// pch.h (stdafx.h in Visual Studio 2017 and earlier)
#include <stdio.h>

pch.hstdafx.h 原始程式檔:

// pch.cpp (stdafx.cpp in Visual Studio 2017 and earlier)
// Compile by using: cl /EHsc /W4 /c /Ycstdafx.h stdafx.cpp
#include "pch.h"

原始程式檔 C2065_pch.cpp

// C2065_pch.cpp
// compile with: cl /EHsc /W4 /Yustdafx.h C2065_pch.cpp
#include <iostream>
#include "stdafx.h"
using namespace std;

int main() {
    cout << "Hello" << endl;   // C2065 'cout': undeclared identifier
                               // C2065 'endl': undeclared identifier
}

若要修正此問題,請將 的 #include <iostream> 新增至先行編譯標頭檔中,或在原始程式檔中包含先行編譯標頭檔之後移動。

範例:遺漏標頭檔

如果您尚未包含宣告識別碼的標頭檔,就會發生此錯誤。 請確定包含識別碼宣告的檔案包含在使用該識別碼的每個原始程式檔中。

// C2065_header.cpp
// compile with: cl /EHsc C2065_header.cpp

//#include <stdio.h>
int main() {
    fpos_t file_position = 42; // C2065: 'fpos_t': undeclared identifier
    // To fix, uncomment the #include <stdio.h> line
    // to include the header where fpos_t is defined
}

另一個可能的原因是,如果您使用初始化運算式清單而不包含 < initializer_list > 標頭。

// C2065_initializer.cpp
// compile with: cl /EHsc C2065_initializer.cpp

// #include <initializer_list>
int main() {
    for (auto strList : {"hello", "world"})
        if (strList == "hello") // C2065: 'strList': undeclared identifier
            return 1;
    // To fix, uncomment the #include <initializer_list> line
}

如果您定義 VC_EXTRALEANWIN32_LEAN_AND_MEANWIN32_EXTRA_LEAN ,您可能會在 Windows 傳統型應用程式原始程式檔中看到此錯誤。 這些預處理器宏會從 windows.hafxv_w32.h 中排除一些標頭檔,以加速編譯。 查看 windows.hafxv_w32.h 尋找排除專案的最新描述。

範例:遺漏右引號

如果您在字串常數後面遺漏結尾引號,就可能發生此錯誤。 很容易混淆編譯器。 遺漏的結尾引號可能是報告錯誤位置之前的數行。

// C2065_quote.cpp
// compile with: cl /EHsc C2065_quote.cpp
#include <iostream>

int main() {
    // Fix this issue by adding the closing quote to "Aaaa"
    char * first = "Aaaa, * last = "Zeee";
    std::cout << "Name: " << first
        << " " << last << std::endl; // C2065: 'last': undeclared identifier
}

範例:在迴圈範圍中使用外部反覆運算器

如果您在迴圈中 for 宣告反覆運算器變數,然後嘗試在迴圈範圍 for 之外使用該反覆運算器變數,就會發生此錯誤。 編譯器預設會 /Zc:forScope 啟用編譯器選項。 如需詳細資訊,請參閱 偵錯反覆運算器支援

// C2065_iter.cpp
// compile with: cl /EHsc C2065_iter.cpp
#include <iostream>
#include <string>

int main() {
    // char last = '!';
    std::string letters{ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" };
    for (const char& c : letters) {
        if ('Q' == c) {
            std::cout << "Found Q!" << std::endl;
        }
        // last = c;
    }
    std::cout << "Last letter was " << c << std::endl; // C2065
    // Fix by using a variable declared in an outer scope.
    // Uncomment the lines that declare and use 'last' for an example.
    // std::cout << "Last letter was " << last << std::endl; // C2065
}

範例:預處理器已移除宣告

如果您參考目前組態未編譯的條件式程式碼中的函式或變數,就會發生此錯誤。 如果您在組建環境中目前不支援的標頭檔中呼叫函式,也可能會發生此錯誤。 如果只有在定義特定預處理器宏時,才能使用某些變數或函式,請確定呼叫這些函式的程式碼只能在定義相同的預處理器宏時編譯。 此問題很容易在 IDE 中發現:如果目前建置組態未定義必要的預處理器宏,函式的宣告會呈現灰色。

以下是當您在偵錯中建置但不是發行時運作的程式碼範例:

// C2065_defined.cpp
// Compile with: cl /EHsc /W4 /MT C2065_defined.cpp
#include <iostream>
#include <crtdbg.h>
#ifdef _DEBUG
    _CrtMemState oldstate;
#endif
int main() {
    _CrtMemDumpStatistics(&oldstate);
    std::cout << "Total count " << oldstate.lTotalCount; // C2065
    // Fix by guarding references the same way as the declaration:
    // #ifdef _DEBUG
    //    std::cout << "Total count " << oldstate.lTotalCount;
    // #endif
}

範例:C++/CLI 類型推算失敗

如果無法從所使用的參數推斷預期型別引數,則呼叫泛型函式時可能會發生此錯誤。 如需詳細資訊,請參閱 泛型函式(C++/CLI)。

// C2065_b.cpp
// compile with: cl /clr C2065_b.cpp
generic <typename ItemType>
void G(int i) {}

int main() {
   // global generic function call
   G<T>(10);     // C2065
   G<int>(10);   // OK - fix with a specific type argument
}

範例:C++/CLI 屬性參數

這個錯誤也可能因為針對 Visual Studio 2005 完成的編譯器一致性工作而產生:參數檢查 Visual C++ 屬性。

// C2065_attributes.cpp
// compile with: cl /c /clr C2065_attributes.cpp
[module(DLL, name=MyLibrary)];   // C2065
// try the following line instead
// [module(dll, name="MyLibrary")];

[export]
struct MyStruct {
   int i;
};