CString s(_T("abc\n"));
_tprintf_s( _T("%s"), s );这个代码可以正常运行
我的疑问是:为什么第二句的s不用调用GetString(),却也能正确地把字符串地址入栈?
我猜测是因为CString的第一个数据成员就是缓冲区
所以写了以下代码class A
{
public:
A( const TCHAR* sz )
{
_tcscpy_s( str, 256, sz );
} TCHAR str[256];
};void Test2()
{
A a(_T("abc\n"));
_tprintf_s( _T("%s\n"), a );
}这样却会崩溃……请教到底CString是如何实现的?
例如CString::operator LPCTSTR而你自定义的类A却没有,你如果要访问A中的字符数组
可以
A a(_T("abc\n"));
_tprintf_s( _T("%s\n"), a.str );
这个按我的理解肯定是有默认机制做过强制转换了
第一个数据成员就是缓冲区, 这个猜测是对的, 这样设计就是为了使用方便, 可以直接把CString 作为一个参数传递进去
传指针,而不是实体。CString内部也是指针。
具体参看MSDN,如果你仅仅是读取字符串,一定不要调用GetString,直接使用就行了,就像你写的这行代码一样:
_tprintf_s( _T("%s"), s );至于说怎么做到的,其实楼上的人都说到了,就是运算符重载。
{
return str;
}运行是一样的结果我的理解是:函数的不定长参数列表在编译时,编译器根本不在乎每个参数的大小,只是简单地把它们入栈,大小就取sizeof(),所以不会调用什么操作符的
TCHAR* str;
就可以实现和CString一样的效果了,因为sizeof(A)==4class B
{
public:
B( const TCHAR* sz )
{
str = new TCHAR[256];
_tcscpy_s( str, 256, sz );
}
~B()
{
delete [] str;
} TCHAR* str;
};void Test3()
{
B b(_T("abc\n"));
_tprintf_s( _T("%s"), b );
}以上代码测试通过~