1

私は MFC クラス CString をサブクラス化しています (クラスに問題はありませんが、私を信じてください。特定の実装のためにこれを行う必要があります)。いくつかの動作をうまくカスタマイズしましたが、CString がフォーマット文字列に渡されるときに発生するように見える暗黙の (LPCTSTR) 演算子を失ったことに気付きました。この魔法は、CString::Format であれ、prinf/sprintf であれ、発生します。例えば:

CString Str = _T("Really cool string");
TCHAR szBuffer[32];
_stprintf(szBuffer, _T("Here it is: %s"), Str);

CString::FormatString は可変引数リストを _vswprintf と _swprintf に渡すだけなので、この魔法が標準の CString でどのように機能するかはわかりません。しかし、それが何をするにしても、私の派生クラスには欠けています。

演算子 (LPCTSTR) は期待どおりに継承され、明示的に呼び出されたときに機能します。

何か案は?

4

2 に答える 2

3

あなたの仮定は間違っています:オブジェクトが-style 関数に渡されるLPCTSTRとき、暗黙的な変換はありません。コンパイラは、それがあなたが望むものであることを知る方法がありません.型情報を推測するためにフォーマット文字列を解析するつもりはありません.CStringprintf

代わりに、オブジェクトはas isCStringに渡されます。ここでの魔法は、暗黙のキャスト演算子がいつどのように呼び出され、C 文字列と互換性があるようにモデル化されるかについて、作成者が間違った仮定を予測したことです。そのために、単一のポインターを含み、v-table を含みません。オブジェクトが -style 関数に渡された場合、このポインターのみがパラメーターとして巻き上げられ、すべてが機能しているように見えます。動作しているように見えることは、未定義の動作の有効な形式であることに注意してください。これ未定義の動作です。printf CStringCStringCStringLPTSTRCStringprintf

CString残りの情報 (現在のサイズ、容量など) がどこに格納されているのか疑問に思っている場合は、メモリ内の文字バッファーのすぐ前に存在します。このようにして、すべての情報が単一のポインターを介して利用可能になります。

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

あなたの本当の問題を解決するために:未定義の動作に頼らないでください。必要に応じて明示的なキャストを使用してください。誰も傷つけません:

_stprintf(szBuffer, _T("Here it is: %s"), static_cast<LPCTSTR>(Str));

キャストの代わりに、次のように呼び出すことができますCString::GetString()

_stprintf(szBuffer, _T("Here it is: %s"), Str.GetString());

また、心に留めておいてください:仮想デストラクタを提供しないクラスから派生すると、リソース リークが発生するのを待っています。つまり、 から派生しないでくださいCString

于 2013-10-17T16:24:50.673 に答える
0

クラスから派生する場合、すべての演算子が継承されるわけではありません。C++ での演算子継承のトピックを Google で検索してください。派生クラスでは、演算子を実装し、単純に基本クラスに転送する必要がある場合があります。

于 2014-08-08T16:15:22.030 に答える