Ошибка компилятора C2065
"identifier" : необъявленный идентификатор
Компилятор не может найти объявление для идентификатора. Существует множество возможных причин этой ошибки. Наиболее распространенными причинами C2065 являются то, что идентификатор не объявлен, идентификатор не указан, заголовок, в котором объявлен идентификатор не включен в файл, или идентификатор отсутствует квалификатор области, например cout
вместо std::cout
этого. Дополнительные сведения о объявлениях в C++см. в статьях "Объявления и определения" (C++).
Ниже приведены некоторые распространенные проблемы и решения более подробно.
Идентификатор не является необъявленным
Если идентификатор является переменной или именем функции, его необходимо объявить, прежде чем его можно будет использовать. Объявление функции должно также включать типы его параметров, прежде чем можно будет использовать функцию. Если переменная объявлена с помощью auto
, компилятор должен иметь возможность выводить тип из инициализатора.
Если идентификатор является членом класса или структуры или объявлен в пространстве имен, он должен быть квалифицирован именем класса или структуры, а также именем пространства имен при использовании вне структуры, класса или пространства имен. Кроме того, пространство имен должно быть передано в область директивой, например, или имя члена должно быть передано в область using
using
объявления, напримерusing std::string;
.using namespace std;
В противном случае необъявленное имя считается необъявленным идентификатором в текущей области.
Если идентификатор является тегом для определяемого пользователем типа, например a class
или struct
, тип тега необходимо объявить, прежде чем его можно будет использовать. Например, объявление struct SomeStruct { /*...*/ };
должно существовать, прежде чем можно объявить переменную SomeStruct myStruct;
в коде.
Если идентификатор является псевдонимом типа, тип должен быть объявлен объявлением using
или typedef
перед его использованием. Например, необходимо объявить 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++ не являются полными по пространству имен или вы не довели std
пространство имен в текущую using
область с помощью директивы, компилятор не сможет найти их. Чтобы устранить эту проблему, необходимо полностью указать имена идентификаторов или указать пространство имен с помощью директивы using
.
Этот пример не может компилироваться из-за того, что cout
он endl
определен в 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;
}
Идентификаторы, объявленные внутри class
, struct
или enum class
типы, также должны быть квалифицированы именем их заключающей области при их использовании за пределами этой области.
Пример: предварительно скомпилированные заголовки не первый
Эта ошибка может возникать, если вы помещаете какие-либо директивы препроцессора, например #include
, #define
или #pragma
до #include
предварительно скомпилированного файла заголовка. Если исходный файл использует предварительно скомпилированный файл заголовка (то есть, если он компилируется с помощью /Yu
параметра компилятора), все директивы препроцессора перед предварительной компиляцией файла заголовка игнорируются.
Этот пример не может компилироваться из-за того, что он endl
определен в <iostream>
заголовке, который игнорируется, так как cout
он включен перед предварительно скомпилированным файлом заголовка. Чтобы создать этот пример, создайте все три файла, а затем скомпилируйте (некоторые версии Visual Studio), stdafx.cpp
а затем скомпилируйте.pch.h
C2065_pch.cpp
// pch.h (stdafx.h in Visual Studio 2017 and earlier)
#include <stdio.h>
Исходный pch.h
файл:stdafx.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
}
Эта ошибка может появить в исходных файлах классического приложения Windows, если вы определяете VC_EXTRALEAN
или WIN32_LEAN_AND_MEAN
WIN32_EXTRA_LEAN
. Эти макросы препроцессора исключают некоторые файлы заголовков из windows.h
и afxv_w32.h
для ускорения компиляции. windows.h
Найдите и afxv_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
}
Пример: удалено объявление препроцессора
Эта ошибка может возникать, если вы ссылаетесь на функцию или переменную, которая находится в условно скомпилированном коде, который не компилируется для текущей конфигурации. Ошибка также может возникать, если вы вызываете функцию в файле заголовка, который в настоящее время не поддерживается в среде сборки. Если определенные переменные или функции доступны только при определении определенного макроса препроцессора, убедитесь, что код, вызывающий эти функции, можно скомпилировать только при определении того же макроса препроцессора. Эта проблема легко обнаружить в интегрированной среде разработки: объявление функции неактивно, если необходимые макросы препроцессора не определены для текущей конфигурации сборки.
Ниже приведен пример кода, который работает при сборке в отладке, но не в выпуске:
// 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;
};