Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
"инициализация": не удается преобразовать из типа1 в "type2"
"преобразование": не удается преобразовать из типа1 в "type2"
Замечания
Компилятор не может неявно преобразовывать из type1type2нее или не может использовать указанный оператор приведения или преобразования.
Компилятор создает C2440, если он не может преобразоваться из одного типа в другой, неявно или с помощью указанного оператора приведения или преобразования. Существует множество способов создания этой ошибки. В разделе "Примеры" перечислены некоторые распространенные.
Примеры
Строковые литералы C++: const
C2440 может быть вызван при попытке инициализации не-constchar* (или wchar_t*) с помощью строкового литерала в коде C++ при установке параметра /Zc:strictStrings соответствия компилятора. В C тип строкового литерала является массивом char, но в C++, это массив const char. В этом примере вызывается ошибка C2440.
// C2440s.cpp
// Build: cl /Zc:strictStrings /W3 C2440s.cpp
// When built, the compiler emits:
// error C2440: 'initializing' : cannot convert from 'const char [5]'
// to 'char *'
// Conversion from string literal loses const qualifier (see
// /Zc:strictStrings)
int main() {
char* s1 = "test"; // C2440
const char* s2 = "test"; // OK
}
Литералы C++20 u8const char8_t
В C++20 или в нижней /Zc:char8_tчасти символ или строка UTF-8 (например u8'a'u8"String", или) имеет тип const char8_t или const char8_t[N]соответственно. В этом примере показано, как изменяется поведение компилятора между C++17 и C++20:
// C2440u8.cpp
// Build: cl /std:c++20 C2440u8.cpp
// When built, the compiler emits:
// error C2440: 'initializing' : cannot convert from 'const char8_t [5]'
// to 'const char *'
// note: Types pointed to are unrelated; conversion requires
// reinterpret_cast, C-style cast or function-style cast)
int main() {
const char* s1 = u8"test"; // C2440 under /std:c++20 or /Zc:char8_t, OK in C++17
const char8_t* s2 = u8"test"; // OK under /std:c++20 or /Zc:char8_t, C4430 in C++17
const char* s3 = reinterpret_cast<const char*>(u8"test"); // OK
}
Указатель на член
Если вы пытаетесь преобразовать указатель в элемент void*, может отображаться C2440. Следующий пример создает C2440:
// C2440.cpp
class B {
public:
void f(){;}
typedef void (B::*pf)();
void f2(pf pf) {
(this->*pf)();
void* pp = (void*)pf; // C2440
}
void f3() {
f2(f);
}
};
Приведение неопределенного типа
Компилятор выдает C2440 при попытке приведения из типа, который объявлен только вперед, но не определен. В этом примере вызывается C2440:
// c2440a.cpp
struct Base { }; // Defined
struct Derived; // Forward declaration, not defined
Base * func(Derived * d) {
return static_cast<Base *>(d); // error C2440: 'static_cast' : cannot convert from 'Derived *' to 'Base *'
}
Несовместимое соглашение о вызовах
Ошибки C2440 в строках 15 и 16 в следующем примере сопровождаются сообщением Incompatible calling conventions for UDT return value.
Определяемый пользователем тип — это определяемый пользователем тип, например класс или structобъединение. Эти типы ошибок несовместимости возникают при возникновении соглашения о вызове определяемого пользователем типа, указанного в возвращаемом типе объявления пересылки, конфликтует с фактическим соглашением о вызове определяемого пользователем типа и при использовании указателя функции.
В примере сначала есть объявления пересылки для функции struct , возвращающей объект struct. Компилятор предполагает, что struct используется соглашение о вызовах C++. Далее — struct определение, которое использует соглашение о вызовах C по умолчанию. Так как компилятор не знает соглашение struct о вызове до тех пор, пока он не завершит чтение всего struct, соглашение о вызове для struct возвращаемого типа get_c2 также считается C++.
За ним следует другое struct объявление функции, возвращающее structзначение . На этом этапе компилятор знает, что structсоглашение о вызове — C++. Аналогичным образом указатель функции, возвращающий structобъект, определяется после struct определения. Компилятор теперь знает struct , что использует соглашение о вызовах C++.
Чтобы устранить ошибки C2440, вызванные несовместимыми соглашениями о вызовах, объявите функции, возвращающие UDT после определения определяемого пользователем типа.
// C2440b.cpp
struct MyStruct;
MyStruct get_c1();
struct MyStruct {
int i;
static MyStruct get_C2();
};
MyStruct get_C3();
typedef MyStruct (*FC)();
FC fc1 = &get_c1; // C2440, line 15
FC fc2 = &MyStruct::get_C2; // C2440, line 16
FC fc3 = &get_C3;
class CMyClass {
public:
explicit CMyClass( int iBar)
throw() {
}
static CMyClass get_c2();
};
int main() {
CMyClass myclass = 2; // C2440
// try one of the following
// CMyClass myclass{2};
// CMyClass myclass(2);
int *i;
float j;
j = (float)i; // C2440, cannot cast from pointer to int to float
}
Назначение нулю внутреннему указателю
C2440 также может произойти, если вы назначаете ноль внутреннему указателю:
// C2440c.cpp
// compile with: /clr
int main() {
array<int>^ arr = gcnew array<int>(100);
interior_ptr<int> ipi = &arr[0];
ipi = 0; // C2440
ipi = nullptr; // OK
}
Пользовательские преобразования
C2440 также может возникать для неправильного использования определяемого пользователем преобразования. Например, если оператор преобразования определен как explicit, компилятор не может использовать его в неявном преобразовании. Дополнительные сведения о пользовательских преобразованиях см. в разделе "Определяемые пользователем преобразования" (C++/CLI)). В этом примере генерируется ошибка C2440.
// C2440d.cpp
// compile with: /clr
value struct MyDouble {
double d;
// convert MyDouble to Int32
static explicit operator System::Int32 ( MyDouble val ) {
return (int)val.d;
}
};
int main() {
MyDouble d;
int i;
i = d; // C2440
// Uncomment the following line to resolve.
// i = static_cast<int>(d);
}
System::Array создание
C2440 также может возникать, если вы пытаетесь создать экземпляр массива в C++/CLI, тип которого является.Array Дополнительные сведения см. в статье Arrays (C++/CLI and C++/CX) (Массивы (C++/CLI и C++/CX)). Следующий пример вызывает C2440:
// C2440e.cpp
// compile with: /clr
using namespace System;
int main() {
array<int>^ intArray = Array::CreateInstance(__typeof(int), 1); // C2440
// try the following line instead
// array<int>^ intArray = safe_cast<array<int> ^>(Array::CreateInstance(__typeof(int), 1));
}
Атрибуты
C2440 также может возникать из-за изменений в функции атрибутов. В следующем примере создается C2440.
// c2440f.cpp
// compile with: /LD
[ module(name="PropDemoLib", version=1.0) ]; // C2440
// try the following line instead
// [ module(name="PropDemoLib", version="1.0") ];
Расширения компонентов вниз приведения
Компилятор Microsoft C++ больше не позволяет const_cast оператору выполнять приведение при компиляции исходного кода в разделе /clr.
Чтобы устранить эту проблему C2440, используйте правильный оператор приведения. Дополнительные сведения см. в разделе "Операторы приведения".
В этом примере возникает ошибка C2440:
// c2440g.cpp
// compile with: /clr
ref class Base {};
ref class Derived : public Base {};
int main() {
Derived ^d = gcnew Derived;
Base ^b = d;
d = const_cast<Derived^>(b); // C2440
d = dynamic_cast<Derived^>(b); // OK
}
Соответствие изменений в соответствии с шаблоном
C2440 может возникать из-за изменений соответствия компилятору в Visual Studio 2015 с обновлением 3. Ранее компилятор неправильно обрабатывал определенные отдельные выражения с тем же типом при определении соответствия шаблона для static_cast операции. Теперь компилятор правильно различает типы, а код, зависящий от предыдущего static_cast поведения, нарушается. Чтобы устранить эту проблему, измените аргумент шаблона на соответствие типу параметра шаблона или используйте reinterpret_cast приведение в стиле C.
В этом примере выдается C2440:
// c2440h.cpp
template<int *a>
struct S1 {};
int g;
struct S2 : S1<&g> {
};
int main()
{
S2 s;
static_cast<S1<&*&g>>(s); // C2440 in VS 2015 Update 3
// This compiles correctly:
// static_cast<S1<&g>>(s);
}
Эта ошибка может появиться в коде ATL, использующего макрос, определенный SINK_ENTRY_INFO в <atlcom.h>.
Инициализация копии списка
Visual Studio 2017 и более поздних версий правильно вызывают ошибки компилятора, связанные с созданием объектов с помощью списков инициализаторов. Эти ошибки не были пойманы в Visual Studio 2015 и могут привести к сбоям или неопределенному поведению среды выполнения. В C++17 copy-list-initialization компилятор должен рассмотреть явный конструктор для разрешения перегрузки, но должен вызвать ошибку, если эта перегрузка на самом деле выбрана.
Следующий пример компилируется в Visual Studio 2015, но не в Visual Studio 2017.
// C2440j.cpp
struct A
{
explicit A(int) {}
A(double) {}
};
int main()
{
const A& a2 = { 1 }; // error C2440: 'initializing': cannot
// convert from 'int' to 'const A &'
}
Чтобы исправить эту ошибку, следует использовать прямую инициализацию:
// C2440k.cpp
struct A
{
explicit A(int) {}
A(double) {}
};
int main()
{
const A& a2{ 1 };
}
CV-квалификаторы при построении класса
В Visual Studio 2015 компилятор иногда ошибочно игнорирует cv-квалификатор при создании объекта класса путем вызова конструктора. Этот дефект может привести к сбою или непредвиденному поведению среды выполнения. Следующий пример компилируется в Visual Studio 2015, но вызывает ошибку компилятора в Visual Studio 2017 и более поздних версиях:
struct S
{
S(int);
operator int();
};
int i = (const S)0; // error C2440
Чтобы исправить ошибку, объявите оператор int() как const.