Dela via


Kompilatorfel C2664

"function" : kan inte konvertera argumentet n från "type1" till "type2"

Anmärkningar

Det här parameterkonverteringsproblemet kan inträffa om en instans av en klass skapas och en implicit konvertering görs på en konstruktor markerad med nyckelordet explicit . Mer information om explicita konverteringar finns i användardefinierade typkonverteringar.

Om ett tillfälligt objekt skickas till en funktion som tar en referens till ett objekt som en parameter måste referensen vara en const referens.

Om funktionen skickas en parameter som inte är av den typ som funktionen förväntar sig skapas ett tillfälligt objekt med hjälp av lämplig konstruktor. Det här temporära objektet skickas sedan till funktionen. I det här fallet används det tillfälliga objektet för att initiera referensen. I tidigare versioner av språket kan alla referenser initieras av temporära objekt.

Så här åtgärdar du C2664

  • Kontrollera prototypen för den angivna funktionen igen och korrigera argumentet som anges i felmeddelandet.

  • Ange en explicit konvertering om det behövs.

C2664 kan också genereras om en klass döljer en medlem i någon av dess basklasser.

Mer information finns i Så gör du: Konvertera System::String till wchar_t* eller char*.

Examples

Följande exempel genererar C2664 och visar hur du åtgärdar det.

// C2664.cpp
// C2664
struct A {
   void f(int i) {}
};

struct B : public A {
   // To fix, uncomment the following line.
   // using A::f;
   void f(A a) {}
};

int main() {
   B b;
   int i = 1;
   b.f(i);   // B::f hides A::f Uncomment the using declaration in B.
}

Det här exemplet genererar även C2664 och visar hur du åtgärdar det.

// C2664b.cpp
// C2664 expected
struct A {
   // To fix, uncomment the following line.
   // A(int i){}
};

void func( int, A ) {}

int main() {
   func( 1, 1 );   // No conversion from int to A.
}

I nästa exempel visas C2664 med hjälp av en strängliteral för att anropa Test, och det visas hur du kan åtgärda problemet. Eftersom parametern är en szString referens måste ett objekt skapas av lämplig konstruktor. Resultatet är ett tillfälligt objekt som inte kan användas för att initiera referensen.

// C2664c.cpp
// compile with: /EHsc
// C2664 expected
#include <iostream>
#include <string.h>
using namespace std;

class szString {
   int slen;
   char *str;

public:
   szString(const char *);
   int len() const {
      return slen;
   }
};

// Simple reference cannot bind to temp var.
void Test(szString &a) {}

// To fix, uncomment the following line.
// void Test(const szString &a) {}

szString::szString(const char * newstr) : slen(0), str(NULL) {
   slen=strlen(newstr);
   str = new char[slen + 1];
   if (str)
      strcpy_s(str, (slen + 1), newstr);
}

int main() {
   Test("hello");
}

Kompilatorn tillämpar C++-standardkraven för att tillämpa const. Det här exemplet genererar C2664:

// C2664d.cpp
// C2664 expected
#include <windows.h>

void func1(LPCSTR &s)
{

}

void func2(LPSTR &s)
{
   func1(s);
}

int main()
{
   return 0;
}

Här är en mer komplex situation där C2664 genereras, inklusive anvisningar om hur du åtgärdar det:

// C2664e.cpp
// compile with: /EHsc
// C2664 expected
#define _INTL
#include <locale>
#include <iostream>

using namespace std;
#define LEN 90

int main( ) {
   char* pszExt = "This is the string to be converted!";
   wchar_t pwszInt [LEN+1];
   memset(&pwszInt[0], 0, (sizeof(wchar_t))*(LEN+1));

   // To fix, delete the following line.
   char* pszNext;

   // To fix, uncomment the following line.
   // const char* pszNext;

   wchar_t* pwszNext;
   mbstate_t state;
   locale loc("C");
   int res = use_facet<codecvt<wchar_t, char, mbstate_t> >
      ( loc ).in( state,
      pszExt, &pszExt[strlen(pszExt)], pszNext,
      pwszInt, &pwszInt[strlen(pszExt)], pwszNext );
   // See earlier comment.
      pwszInt[strlen(pszExt)] = 0;
   wcout << ( (res!=codecvt_base::error) ?
                       L"It worked! " : L"It didn't work! " )
   << L"The converted string is:\n ["
   << &pwszInt[0]
   << L"]" << endl;

   exit(-1);
}

En uppräkningsvariabel konverteras inte till dess underliggande typ så att ett funktionsanrop uppfylls. Mer information finns i uppräkningsklass. Följande exempel genererar C2664 och visar hur du åtgärdar det.

// C2664f.cpp
// compile with: /clr
using namespace System;
public enum class A : Char {
   None = 0,
   NonSilent = 1,
};

void Test(Char c) {}

int main() {
   A aa = A::None;
   Test(aa);   // C2664
   Test(Char(aa));   // OK - fix by using a conversion cast
}

En bugg i midl-kompilatorn gör att en wchar_t typ genereras som en osignerad förkortning i typbiblioteket. Lös det här felet genom att antingen kasta typen i C++-källkoden eller definiera typen som en sträng i idl-filen.

// C2664g.idl
import "prsht.idl";

[ object, uuid(8402B8F1-BF7F-4B49-92D4-C2B9DF4543E9) ]

interface IMyObj1 : IUnknown {
   HRESULT  teststr([in, string] wchar_t *wstr);
   HRESULT  testarr([in, size_is(len)] wchar_t wstr[], [in] int len);
   HRESULT  testbstr([in] BSTR bstr);
};

[  uuid(44463307-CBFC-47A6-8B4F-13CD0A83B436) ]
library myproj1 {
   [  version(1.0), uuid(D8622C12-5448-42B8-8F0E-E3AD6B8470C1) ]
   coclass CMyObj1 { interface IMyObj1; };
}

C2664 höjs också med hjälp wchar_t av vid portning av kod från Visual C++ 6.0 till senare versioner. I Visual C++ 6.0 och tidigare wchar_t var en typedef för unsigned short och därför implicit konvertibel till den typen. Efter Visual C++ 6.0 wchar_t är dess egen inbyggda typ, enligt vad som anges i C++-standarden, och är inte längre implicit konvertibel till unsigned short. Se /Zc:wchar_t (wchar_t är ursprunglig typ).

Följande exempel genererar C2664 och visar hur du åtgärdar det.

// C2664h.cpp
#import "C2664g.tlb"
using namespace myproj1;

int main() {
   IMyObj1Ptr ptr;

   wchar_t * mybuff = 0;
   BSTR bstr = 0;
   int len;
   ptr->teststr(mybuff);
   ptr->testbstr(bstr);
   ptr->testarr(mybuff, len);   // C2664
   ptr->testarr((unsigned short *)mybuff, len);   // OK - Fix by using a cast
}

C2664 orsakas också om kompilatorn inte kan härleda mallargument.

// C2664i.cpp
#include <stdio.h>
template <class T, int iType=0>
class CTypedImg {
public:
   CTypedImg() {}
   void run() {}

   operator CTypedImg<T>& () {
      return *((CTypedImg<T>*)this);
    }
};

template <class t1>
void test(CTypedImg<t1>& myarg) {
   myarg.run();
}

int main() {
   CTypedImg<float,2> img;

   test((CTypedImg<float>&)img);   // OK
   test<float>(img);   // OK
   test(img);   // C2664 - qualify as above to fix
}