• ベストアンサー

文字列クラスをoperatorオーバーロードで実装したい

ATLにCStringという文字列クラスがあり、それを参考に operatorによる演算子オーバーロードで同じようなものを開発していて 一つだけ分からないことがありました。 CStringだと関数に文字列を受け渡す時にこのようなことができます。 #include <windows.h> #include <tchar.h> #include <atlstr.h> void func( LPCTSTR String ) {   MessageBox( NULL, String, NULL, MB_OK ); } int main() {   CString cStr = _T("テスト");   func( cStr ); } 分からないのはfunc( cStr );の部分です。 このように関数に受け渡す時のオーバーロードはどのように書けば良いのでしょうか? 何かEffectiveC++の最初の方の簡単な例題にこれと同様なやり方が あった気がしますが手元に無いため確認が取れなくて困ってしまっています・・。

noname#88356
noname#88356

質問者が選んだベストアンサー

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

「文字列クラス」の中で operator LPCTSTR() を定義する.

noname#88356
質問者

お礼

すみません。まさにそれでした。 質問直後に思い出してしまいました。でも回答ありがとうございます。

その他の回答 (2)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

ついでですが, 「型A から型B に変換する」のは 2通りの書き方があります: 1.B に「型A のオブジェクトを受け取る (1引数で呼び出せる) コンストラクタ」を作る 2.A に「型B への変換演算子」を作る どちらも同じように「型A のオブジェクトを型B に変換する」ためのユーザ定義演算子として動作します (ので, 両方あるとダメ). A, B が両方ともユーザ定義のクラスであればどちらの方法でもいいのですが, 一方が組み込み型だと (そこに手を加えることは不可能なので) もう一方の「ユーザ定義のクラス」で定義することしかできません (A, B ともに組み込み型の場合はそもそもプログラムで変換方法を定義できない). つまり A が組み込み型だと1のみ, B が組み込み型だと2のみが可能です. 今回はこの最後のパターンにあてはまるので, 「文字列クラス」に変換演算子を定義する必要があります.

noname#88356
質問者

お礼

そういうものもあったんですね。勉強してみることにします。ありがとうございました!

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

この場合だと、 class CString {  … public:  operator LPCTSTR() const;  … }; というメンバを定義すれば実現できます。 やや分かりにくいですが、返却値の型はLPCTSTRになります。 ただ、このような変換関数を定義するのは、あまりよい設計とはいえません。 できれば、std::basic_stringのc_strのようにメンバ関数にするか、もっと欲を言えば、非メンバ関数にした方がよいでしょう(friendが必要になるでしょうが)。 内部で管理するリソースは、外から触れないようにした方がよいのです。どうしてもやるなら、プログラマに警告する意味でも、構文をなるべく汚くすべきです。

noname#88356
質問者

お礼

なるほど・・とても参考になりました。ありがとうございます。

関連するQ&A

  • ダイアログへ文字列を表示させる方法(API)

    TCHAR s[80] = "Test"; MessageBox(NULL, s, "題名", MB_YESNO); としてダイアログを表示させるのと同じように、 ダイアログボックスをリソースエディタで作成し 作成したダイアログ内に、文字列を表示させるには どのようにしたら良いでしょうか? 作成したダイアログは、MessageBox関数で作成されるものと同じ。 表示させたい文字列は、MessageBox関数の第2パラメータのTCHAR型変数sと同じ。 ダイアログ内の表示させたい所の識別子は、IDC_STATIC。 MS VC++ & Win98 の環境で作成してます。

  • C言語で文字列の比較をしたいです。

    C言語で文字列の比較をしたいです。 現在Visual C++ 2008 Express EditionをつかってWindowsプログラミングの勉強をしているのですが、文字列同士の比較で上手くいかなくなってしまったので、教えてください。 プログラムは、確認ボタンを押すとエディットボックスの内容を取得し、取得された内容が「"abc"」であれば処理を実行するというものです。 //宣言など #include <windows.h> #include <windowsx.h> #include <stdio.h> #include <stdlib.h> #include <tchar.h> #include <string.h> static TCHAR chords[512]; //WM_CREATEの部分 hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT") , TEXT("abc") , WS_CHILD | WS_VISIBLE | ES_LEFT |ES_MULTILINE | WS_VSCROLL , 10 , 150 , 300 , 200 , hWnd, (HMENU)4, hInst , NULL); //取得 GetWindowText(hEdit, chords, 512); //判定 if(_tcscmp(chords, TEXT("abc")) == 0)実行する処理; ソースはかなり省略されていますが、エディットボックスとボタンは機能しているようです。 実行すると 「 error C2664: 'wcscmp' : 1 番目の引数を 'TCHAR *[]' から 'const wchar_t *' に変換できません。」 というエラーが出ます。 UnicodeやTCHAR周りの問題のような気がしますが、どうすれば上手くいくのでしょうか?

  • 文字列の変換

    超 C++ 初心者です。 コンソールで "Hello, world!" を学んでからニ,三ヶ月程度です。 C++ の string クラスのメンバ関数 c_str() を用いることで /**  * string(C++ の文字列)から C の文字列(文字配列)を取り出し  * その先頭のアドレスを返す  */ ということができるのを学びました。 今 C++ の string および VC++ の CString の変換をしたいと思っています。 例えば VC++ で MFC アプリケーションを作っているとき, C++ の string である temp を VC++ の CString として使えるように するには,どういう手段をとればよいのでしょうか。 逆に VC++ の CString である temp を C++ の string として使うとき の方法もご教授ねがえれば幸いです。 超初心者につき,方法があまりにも難しいようでしたら断念することも考えています。

  • 文字列の置換をCStringで(C++)

    あいうえお(5)かきく(8)けこ という文字列の ”(数字)”を別の文字列”さささささ” に変えたいんです。 (つまり、正解は あいうえおさささささかきくさささささけこ) replace関数を使ってみようと思ったのですが、 string型のものならば、 (開始場所、変えたい文字数、変えたい文字列) を引数にすればいいのはわかるのですが、 これを、CStringでやりたいのです。 ヘルプを見てもCStringのreplace関数は (変更前の文字列、変更後の文字列)を引数にする、 となっていて、私のように(数字)というアバウトな場合にはむかないのかとも思いますが、他のプログラムとの関係で、CString型がいいのです。 ややこしくてすいませんが、アドバイスお願いいたします。

  • CString: 識別子が見つかりません

    開発環境:Visual c++ 2008 Express Edion OS:Win XP Pro 次のエラーが表示されていて解決できません。 エラー内容は 1>d:\vc_source\dump\dump\Form1.h(448) : error C3861: 'CString': 識別子が見つかりませんでした です。 ちなみにinclude文は以下です。 #include <Windows.h> #include <stdio.h> #include <stdlib.h> #include <tchar.h> #include <string> #include <cstring> やりたいことは String型からCString型を経由して、TCHAR型へ変換することです。またはその逆方法の変換です。そのためにCString型は必要になるのですが、そこでコンパイルエラーになっています。 知っているかがおりましたら、教えて下さい。

  • 関数のコピー

    以下のようなソースがあります。 していることは、char配列に関数をコピーしています。それを関数ポインタに変換して、実行しています。 自作の場合はできるのですが、 MessageBoxをコピーすると以下(字数の関係上無理でした。)のようにメモリ内容がなっており、そのままコピーしたつもりですが、若干異なっております。 どのようにすればMessageBoxがじっこうできるのか, 教えていただきたく質問しました。 よろしくお願いします。 mb,code3が該当分です。 //ソース #include<stdio.h> #include<memory.h> #include<windows.h> int func(int cnt) { return cnt*10; } int func2(int cnt,int cnt2) { return cnt+cnt2; } char *func3() { return "Hello"; } int main() { int (*fa)(int); //MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaotion,UINT uType); int (*fm)(int,int); int (*mb)(HWND,LPCTSTR,LPCTSTR,UINT); char *(*hl)(void); /*fa=func; printf("%d",fa(5)); getchar(); */ char code[12800]; char code2[12800]; char code3[80000]; char code4[12800]; memset(code,0,12800); memset(code2,0,12800); memset(code3,0,80000); memset(code4,0,12800); memcpy(code,(char *)func,12800); memcpy(code2,(char *)func2,12800); memcpy(code3,(char *)MessageBox,80000); memcpy(code4,(char *)func3,12800); fa=(int(*)(int))(void *)code; fm=(int(*)(int,int))(void *)code2; mb=(int(*)(HWND,LPCTSTR,LPCTSTR,UINT))(void *)code3; hl=(char *(*)(void))(void *)code4; printf("%d\n",fa(3)); printf("%d\n",fm(3000,10)); printf(hl()); MessageBox(NULL,"","",MB_OK); mb(NULL,"","",MB_OK); getchar(); return 0; }

  • fgetsで2行目から文字化け

    fgetsでファイルを一行ずつ読み込みたいのですが、二行目以降が文字化けしてしまいます。 ******* ソース ******* #include <windows.h> #include <stdio.h> FILE *fp; if ((fp = fopen("textlist.txt", "r")) == NULL){ MessageBox(NULL, TEXT("ファイルを開けません"), NULL, NULL); exit (1); } while (1) { TCHAR buf[128] = {0}; if (fgets(buf, sizeof(buf), fp) == NULL) break; MessageBox(NULL,buf,NULL,NULL); } fclose(fp); ***** textlist.txt ***** あいうえお かきくけこ さしすせそ メッセージボックスの一回目は正しく"あいうえお"と表示されますが、二回目・三回目は文字化けしています。 最終的に一行ずつ分けて配列に入れたいので、fgetsで出来たらと思っています。 よろしくお願いします。

  • C++で>>演算子のオーバーロード

    C++学習者です。 Visual Studio Community 上で、ある教本を使って勉強しています。 現在Stringというクラスを作って、文字列に対して連結や部分文字列の取り出しなどができるようにするための色々な演算子のオーバーロードをする関数を定義していますが、疑問点がありますので、お聞きしたいと思います。 Stringクラスのプライベート変数は、文字列の長さを表すlength と、new 演算子で動的に確保するメモリー領域の始まりのアドレスを表す *sPtr の二つです。 クラス内ではパブリックなメンバー関数としていろいろな演算子がオーバーロードされていて、これらについてはよく理解できるのですが、friend 関数として定義されている入力演算子(>>)について納得がいかない部分があります。 その関数は次のようになっています。 istream &operator>>(istream &input, String &s) { char temp[100]; input >> setw(100) >> temp; s = temp; return input; } わからないのは s = temp; の部分です。 sはStringクラスのオブジェクトで、temp は単なる文字列なのに、なぜ代入できるのでしょうか? 代入演算子=のオーバーロード関数も下に挙げますが、この中でも単なる文字列をStringクラスのオブジェクトに代入できるようにはなってないように見えます。 const String &String::operator=(const String &right) { if (&right != this){ // avoid assignment of itself delete [ ] sPtr; length = right.length; sPtr = new char[ length + 1]; strcpy(sPtr, right.sPtr); } else cout<< "attempted to assign a String to itself \n\n"; return *this; } どなたか答えて頂けると有難いです。

  • _tcscat がうまくいきません(VC++2008)

    以下のように入力し、ビルドすると 「error C2664: 'wcscat' : 1 番目の引数を 'LPCTSTR' から 'wchar_t *' に変換できません。」となり、うまくいきません。 ダイアログに「テストです。」と表示させたいです。一体どうしたらよいのでしょうか?ご教授ください~。 環境は、WindowsXP SP2 & Visual C++ 2008 Express Edition です。 なお、文字セットは「Unicode 文字セットを使用する」に設定してあります。 //----------------------------------------------------------- #include <Windows.h> #include <tchar.h> INT WINAPI WinMain( HINSTANCE hInst,HINSTANCE,LPSTR,INT){ LPCTSTR str1 = _T("テスト"); LPCTSTR str2 = _T("です。"); _tcscat( str1, str2 ); MessageBox(NULL,str1,_T("Dialog"),MB_OK); return 0; }

  • 文字列クラスを作りたいと思っています

    文字列クラスを作りたいと思っています。 以下のようなところまでは作れましたが、 エラーがでてしまいます。 どこかおかしいところがあるのでしょうか? *********************************************** #include<stdio.h> #include<string.h> class stt { public: char *str; int len; bool maked; stt::stt() { len=0; str=NULL; maked=false; } stt::~stt() { delete[] str; } stt &operator =(char *c) { if(maked) { delete[] str; maked=false; } len=strlen(c); str=new char[len]; strcpy(str,c); maked=true; return (*this); } virtual operator char*() { return str; } }; int main() { stt s; s="Hello World"; printf(s); getchar(); return 0; } ***********************************************

専門家に質問してみよう