C++ C2440 错误,无法从 'std::_String_iterator<_Elem,_Traits,_Alloc>' 转换为 'LPCTSTR'

C++ C2440 Error, cannot convert from 'std::_String_iterator<_Elem,_Traits,_Alloc>' to 'LPCTSTR'

本文关键字:Alloc Traits Elem gt 转换 LPCTSTR lt iterator 错误 std C++      更新时间:2023-10-16

不幸的是,我的任务是编译一个旧的C++DLL,以便它能在Win 7 64位机器上运行。我没有任何C++经验。我把其他问题弄得一团糟,但这件事难住了我,我在其他地方也找不到解决办法。以下代码引发了一个C2440编译器错误。

错误:"错误C2440:":无法从'std::_String_iterator<_Elem,_Traits,_Alloc>'转换为'LPCTSTR'"

代码:

#include "StdAfx.h"
#include "Antenna.h"
#include "MyTypes.h"
#include "objbase.h"
const TCHAR* CAntenna::GetMdbPath()
{
    if(m_MdbPath.size() <= 0) return NULL;
    return LPCTSTR(m_MdbPath.begin());
}

"m_MdbPath"在Antenna.h文件中定义为字符串m_MdbPath;

任何人能提供的帮助或指导都是非常有帮助的。提前谢谢。如果需要,我很乐意提供有关代码的更多详细信息。

std::string有一个.c_str()成员函数,它应该可以完成您想要的任务。它将返回一个const char*(const wchar_t*和std::wstring)。std::string还有一个empty()成员函数,我建议使用nullptr而不是NULL宏。

const TCHAR* CAntenna::GetMdbPath()
{
    if(m_MdbPath.empty()) return nullptr;
    return m_MdbPath.c_str();
}

解决方案:

const TCHAR* CAntenna::GetMdbPath()
{
    if(m_MdbPath.size() <= 0) return NULL;
    return m_MdbPath.c_str();
}

如果可以保证程序使用MBCS字符集选项(或者如果使用Visual Studio,则"字符集"选项设置为Not Set),则会起作用,因为std::string字符类型与TCHAR类型相同。

但是,如果您的构建是UNICODE,那么std::string字符类型将与TCHAR类型不同,因为TCHAR被定义为宽字符,而不是单字节字符。因此,返回c_str()将给出编译器错误。因此,您的原始代码,加上返回std::string::c_str()的临时修复可能会起作用,但就所使用的类型而言,这在技术上是错误的。

您应该直接使用提供给函数的类型——如果类型是TCHAR,那么您应该使用基于TCHAR的类型,但TCHAR是一种根据构建类型更改定义的类型。

事实上,如果代码是UNICODE构建的,那么它在运行时会失败得很惨,为了修复编译器错误,您将其转换为LPCTSTR以保持编译器安静。不能将字符串指针类型强制转换为其他字符串指针类型。铸造不是转换,仅仅铸造不会将窄弦转换为宽弦,反之亦然。你至少会使用或显示一些奇怪的字符,更糟糕的是,一个程序会出现随机的奇怪行为和崩溃。

除此之外,您永远不知道什么时候真正需要构建UNICODE版本的DLL,因为MBCS构建变得越来越罕见。根据你最初的帖子,DLL对TCHAR的使用表明,是的,这个DLL可能(甚至已经)是为UNICODE构建的。


您可以使用一些替代解决方案。请注意,其中一些解决方案可能需要在字符串类型之外进行额外的编码更改。如果使用C++流对象,可能还需要更改它们以匹配字符类型(例如,std::ostreamstd::wostream


解决方案1。使用typedef,其中要使用的字符串类型取决于生成类型

例如:

#ifdef UNICODE
   typedef std::wstring tchar_string;
#else
   typedef std::string tchar_string;
#endif

然后使用CCD_ 20而不是CCD_。在MBCS和UNICODE构建之间切换将在不必强制转换字符串类型的情况下工作,但需要更改编码。


解决方案2。使用typedef可以使用TCHAR作为std::basic_string模板中的基本字符类型

例如:

typedef std::basic_string<TCHAR> tchar_string;

并在您的应用程序中使用tchar_string。您获得了与std::(w)string相同的公共接口,这允许您在MBCS和UNICODE构建之间无缝切换(就字符串类型而言)。


解决方案3。使用UNICODE构建并完全放弃MBCS构建

如果您正在构建的应用程序是一个新应用程序,那么UNICODE是创建新应用程序时的默认选项(至少在Visual Studio中是这样)。那么您真正需要做的就是使用std::wstring

这与确保使用MBCS的原始解决方案有点相反,但如果只有一种构建类型,则IMO此解决方案更有意义。MBCS构建变得越来越罕见,基本上应该只用于遗留应用程序。