在CString :: Format中使用CString对象

时间:2018-01-13 23:32:35

标签: c++ mfc

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

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);

强制转型?

2 个答案:

答案 0 :(得分:4)

来自CStringT课程模板的文档:

  

您可以自由地将CStringT个对象替换为PCXSTR函数参数。

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

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

就记录的合同而言。要理解为什么通过可变参数列表传递CStringT仍然(技术上)安全,有助于查看实现 1

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

与此Q& A的讨论无关,但为了完整起见,以下是CSimpleStringT如何跟踪附加数据(如字符串长度或引用计数)的简要说明。唯一的数据成员m_pszData指向CStringData类型的结构,它由一个常量大小的初始序列组成,存储簿记信息,紧接着是一个长度为nAllocLength + 1的字符数组。 m_pszData指向此数组,并通过指针算法检索其他数据,由私有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附带的实现,理论上可以在不事先通知的情况下进行更改。

答案 1 :(得分:2)

如果您不使用演员表,则按值传递CString对象。这恰好因为CString的实现方式而有效,并且无法保证CString实现永远不会改变。