c++ - 在 CString::Format 中使用 CString 对象

标签 c++ mfc

我可以在 CString::Format 中使用 CString 吗,如下所示:

CString text = _T("text");
CString format;
format.Format(_T("%s"), text);

同样的方法在MFC源文件和MFC书籍中都有看到。例如:

//From MFC file:
//C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\src\mfc\
//    afxeditbrowsectrl.cpp
BOOL CMFCEditBrowseCtrl::OnIllegalFileName(CString& strFileName)
{
    CString strError;
    CString strMessage;
    ...
    strMessage.Format(_T("%Ts\r\n%Ts"), strFileName, strError);
    //I don't know what is the `T` in `"%Ts"` !
    ...
}

然而,其他 MFC 源文件使用 LPCTSTR 转换。示例:

format.Format(_T("%s"), (LPCTSTR)text);

Actor 是强制性的吗?

最佳答案

来自 CStringT 类模板的文档:

You can freely substitute CStringT objects for PCXSTR function arguments.

每当函数参数需要一个常量 C 风格字符串时,您可以传递一个 CStringT 对象,该对象通过调用 operator PCXSTR() 隐式转换。 .

带有 variadic arguments 的函数,另一方面,采用未类型化的参数列表。在这种情况下,传递 CStringT 对象(在语义上)预期为 PCXSTR 的地方是不安全的。编译器无法知道它应该发出代码来执行隐式转换。您负责自己执行转换,方法是调用 operator PCXSTR(),或调用 GetString()类(class)成员。

就记录在案的契约(Contract)而言。要理解为什么通过可变参数列表传递 CStringT 仍然(技术上)安全,查看实现1 会有所帮助:

CSimpleStringT类模板是所有支持的字符串类的基础。它包含类型为 PCXSTR 的单个(私有(private))数据成员,并且没有虚函数,使其成为 standard layout。类型。因此,二进制表示与其唯一成员的二进制表示相同,即指向以零结尾的字符数组的指针。


与本问答的讨论无关,但为了完整起见,这里简要解释一下 CSimpleStringT 如何跟踪附加数据(如字符串长度或引用计数)。唯一的数据成员m_pszData 指向类型为CStringData 的结构。 ,它由一个恒定大小的初始序列组成,用于存储簿记信息,紧接着是一个长度为 nAllocLength + 1 的字符数组。 m_pszData 指向这个数组,附加数据通过指针算法检索,由私有(private) GetData() 成员实现:

CStringData* GetData() const throw()
{
    return( reinterpret_cast< CStringData* >( m_pszData )-1 );
}

类布局总结如下图:

                        +------------------------+
                        | CStringData            |
                        +========================+
                        | pStringMgr             |
+----------------+      | nDataLength            |
| CSimpleStringT |      | nAllocLength           |
+================+      | nRefs                  |
| m_pszData      | ---> | data[0]                |
+----------------+      | data[1]                |
                        . ...                    .
                        | data[nAllocLength - 1] |
                        | data[nAllocLength]     |
                        +------------------------+

1 这是基于 Visual Studio 2017 附带的实现,理论上可以更改,恕不另行通知。

关于c++ - 在 CString::Format 中使用 CString 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48245284/

相关文章:

c++ - 无法从 C++ DLL 导出函数

c++ - 获取 "embedded"变量或对象的 getter 是否被允许/普遍使用?

c++ - 套接字在处理后打开,打开它完成

c++ - 无法打开文件c++

visual-c++ - 将 CTaskDialog 的主图标设置为问题?

c++ - 无法打开源文件 "afxwin.h"/"afxext.h"/"afxdisp.h"/"afxdtctl.h"/"afxcmn.h"/afxdisp.h 等

c++ - 如何在 qt 中更改一个 QBarSet 栏/元素颜色?

c++ - 静态多态定义与实现

c++ - 我可以在不使用标准 api 函数的情况下创建流程吗?

c++ - 更改功能区按钮的文本颜色