编译器错误 C2440

更新:2007 年 11 月

错误消息

“conversion”: 无法从 “type1”转换到“type2”

编译器无法从“type1”强制转换到“type2”。

标准 C++ 库中执行的一致性和更新工作可能导致 C2440。 有关更多信息,请参见 标准 C++ 库更改:Visual C++ .NET 2003Visual C++ 版本中的库更改

示例

如果试图将指向成员的指针转换为 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);
   }
};

下一个示例的 15 和 16 行上的 C2440 错误将用 Incompatible calling conventions for UDT return value 消息限定。(UDT 指用户定义的类型,如类、结构或联合。) 在前向声明的返回类型中指定的 UDT 调用约定与该 UDT 的实际调用约定有冲突并且涉及函数指针时,会导致上述类型的不兼容性错误。

在该示例中,我们首先拥有某结构和返回该结构的函数的前向声明;编译器假定该结构使用 C++ 调用约定。然后我们生成该结构的定义,默认情况下,该结构定义使用 C 调用约定。因为编译器在读完整个结构前,不知道该结构的调用约定,所以也假定在 get_c2 的返回类型中该结构的调用约定为 C++。

该结构后面跟有另一个返回该结构的函数声明,但在此时,编译器知道该结构的调用约定为 C++。同样,返回该结构的函数指针在结构定义之后定义,所以编译器知道该结构使用 C++ 调用约定。

若要解决由于不兼容的调用约定而产生的 C2440,请在 UDT 定义之后声明返回 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 = (CMyClass)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。有关用户定义的转换的更多信息,请参见 User-Defined Conversions。下面的示例生成 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);
}

如果试图创建 Visual C++ 数组的实例,该数组的类型为 Array,也会出现 C2440。有关更多信息,请参见array。 下面的示例生成 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") ];

生成此错误的原因还可能是为 Visual C++ 2005 执行的编译器一致性工作:对使用 /clr 编程的源代码进行编译时,Visual C++ 编译器不再允许 const_cast Operator向下的强制转换。

要解决此 C2440,请使用正确的强制转换运算符(有关更多信息,请参见 Casting Operators)。有关更多信息,请参见 Visual C++ 2005 编译器中的重大更改

下面的示例生成 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
}

使用 /clr:oldSyntax 也会生成 C2440。下面的示例生成 C2440。

// c2440h.cpp
// compile with: /clr:oldSyntax
__gc class Base {};
__gc class Derived : public Base {};
int main() {
   Derived *d = new Derived;
   Base *b = d;
   d = const_cast<Derived*>(b);   // C2440
   d = dynamic_cast<Derived*>(b);   // OK
}