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是如何实现的?

解决方案 »

  1.   

    因为CString重载了很多操作
    例如CString::operator LPCTSTR而你自定义的类A却没有,你如果要访问A中的字符数组
    可以
    A a(_T("abc\n"));
        _tprintf_s( _T("%s\n"), a.str );
      

  2.   

    按你的猜测,_tprintf_s 传的应该是对象地址而不是对象本身了,
    这个按我的理解肯定是有默认机制做过强制转换了
      

  3.   

    CString 的大小只有4字节, 直接传进去的, 
    第一个数据成员就是缓冲区, 这个猜测是对的, 这样设计就是为了使用方便, 可以直接把CString 作为一个参数传递进去
      

  4.   

        _tprintf( _T("%s\n"), &a );
    传指针,而不是实体。CString内部也是指针。
      

  5.   

    随便的调用CString.GetString()是一个错误,这个错误非常多的人都犯,包括一些很多星星的人。
    具体参看MSDN,如果你仅仅是读取字符串,一定不要调用GetString,直接使用就行了,就像你写的这行代码一样:
    _tprintf_s( _T("%s"), s );至于说怎么做到的,其实楼上的人都说到了,就是运算符重载。
      

  6.   

    不是重载操作符的问题,我试过重载了operator const TCHAR* () const
    {
    return str;
    }运行是一样的结果我的理解是:函数的不定长参数列表在编译时,编译器根本不在乎每个参数的大小,只是简单地把它们入栈,大小就取sizeof(),所以不会调用什么操作符的
      

  7.   

    我知道怎么回事了,如果把A类的数据成员改成
    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 );
    }以上代码测试通过~
      

  8.   

    准确地讲,即使A的sizeof不为4,只要保证它的第一个数据成员是TCHAR*类型的缓冲区就可以了