std::wstringの継承による文字列代入処理の実装方法

このQ&Aのポイント
  • VisualC++2008ExpressEditionで文字や数字を簡単に扱えるクラスを作成しようとしています。
  • クラスmultiStringは、std::wstringを継承しています。
  • しかし、wchar_tをクラスに代入する処理の実装でエラーや例外が発生しています。継承した場合はどのように実装すればいいでしょうか?
回答を見る
  • ベストアンサー

std::wstringの継承

#include<iostream> #include<string> #include <stdlib.h> #include <locale.h> #include <boost/lexical_cast.hpp> using boost::lexical_cast; using namespace std; VisualC++2008ExpressEditionで文字や数字を簡単に扱えるクラスを今作ろうとしていて以下のように作ってみました。 class multiString:public std::wstring{ public:   multiString(const wchar_t *ws){     /* multiString class自体に代入 */   } }; しかし、このwchar_tをクラスに代入する処理として、 multiString(const wchar_t *s)std::wstring(s); とすると、「error C2082: 仮パラメータ 's' が再定義されました。」となりますし、 multiString(const wchar_t *s)*this=s; とすると、例外が発生してしまします。 wstringだったら、簡単に代入処理として出来るのですが、継承した場合はどの様に実装すればいいのでしょうか? 宜しくお願いします。

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

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

正確なエラーメッセージは 「すべてのコントロールのパス, 関数を回帰するとランタイムスタックオーバーフローが発生します」 というもの. ここの this は multiString * です. そして operator = は継承されないので, コンストラクタ中の *this = s; における operator = は wstring::operator = ではなく multiString::operator = です. しかも今の場合このメンバー関数を定義していないので, コンパイラが自動生成した multiString &multiString::operator =(const multiString &) を使います. ところが, 代入の右辺は const wchar_t * ですからこの代入演算子にあわせるためにコンストラクタ multiString::multiString(const wchar_t *) を呼び出そうとします. これで無限再帰が成立. 明示的に std::wstring::operator = を呼び出せばいいんだけどね....

glarelance
質問者

お礼

なるほど、確かに、 multiString(const wchar_t *cs){std::wstring::operator =(cs);} という風に、コンストラクタを書いておくとうまくいきました。 どうも有り難うございました。

その他の回答 (3)

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

え~と.... #1 の言われるように multiString(const wchar_t *s) : std::wstring(s) {} でいいのでは? しかし Visual C++ も賢いなぁ. 確かに multiString(const wchar_t *s){*this=s;} だとスタックオーバーフローするよ.... コンパイラのいう通りだ....

glarelance
質問者

お礼

確かに、「multiString(const wchar_t *s) : std::wstring(s) {}」と書くと代入できますが、「multiString(const wchar_t *s){*this=s;}」と書いてあっても、wstringにはwchar_tを「operator=」で代入できると思うのですが、このようにすると何故、スタックオーバーフローとなってしまうのでしょうか?

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

結局のところ, どのようなプログラムを書いたのですか? できる限り省略しないで全体を出してください.

glarelance
質問者

お礼

解答有り難うございます。 実際私が書いたプログラムとしては、テストのためQ1の人へのお礼で書いたように、最初に示したソースの「/* multiString class自体に代入 */」の部分に、 multiString(const wchar_t *s){std::wstring(s);} とか multiString(const wchar_t *s){*this=s;} と、書いただけです。 宜しくお願いします。

glarelance
質問者

補足

補足です。 multiString(const wchar_t *s){*this=s;} と「/* multiString class自体に代入 */」の部分に書いたときは、 void main(void){ multiStringstr(L"atatea"); } とメイン文に書いてやると例外が発生します。 宜しくお願いします。

回答No.1

>multiString(const wchar_t *s)std::wstring(s); こんな記述できますか? multiString(const wchar_t *s) : std::wstring(s) {} では? あと、operator + あたりが必要になったような気もする。

glarelance
質問者

お礼

すみません、正しくは multiString(const wchar_t *s){std::wstring(s);} とか、 multiString(const wchar_t *s){*this=s;} として、試したんです。 一応、 this->assign(s); としてやれば、代入できるようにはなったのですが、wstringクラスを継承した場合、何故このようなエラーが出るのでしょうか?

関連するQ&A

  • boost::regexで、日本語に利用ついて

    boost_1_47を利用して、置換を行おうとしているのですが、「VIII」を置換しようとするとエラーになります。たぶん「5B」が入っているからかと思うのですが、どのように対処したらよいのでしょうか? #include <boost/regex.hpp> using namespace std; using namespace boost; const boost::regex str("VIII"); よろしくお願いします。

  • boost::lexical_castで16進数文字列を数値に変換する

    boost::lexical_castで16進数文字列を数値に変換する 次のコードで試しましたが実行時例外になります。 16進数文字列をlexical_castで扱う方法を教えてください。 #include <boost/lexical_cast.hpp> string ss = "0x1234"; int n = boost::lexical_cast<int>(ss); よろしくお願いします。

  • boost::archive::xml_oarchiveについて

    boostのコンパイルが通りません。調べられるだけ調べたのですが、原因として表示されるmake_nvpを利用しても、boost::STATIC_ASSERTION_FAILUREが発生します。わかる方ご教授お願いします。 #define BOOST_LIB_NAME boost_serialization #include <boost/config/auto_link.hpp> #include <boost/serialization/string.hpp> #include <boost/serialization/access.hpp> #include <boost/serialization/nvp.hpp> #include <boost/archive/xml_oarchive.hpp> #include <fstream> class FooData { private: int Data; friend class boost::serialization::access; template <class Archive> void serialization(Archive& ar, const unsigned int version) { ar & boost::serialization::make_nvp("Data",Data) } }; void main(void) { FooData data; //アーカイブ作成 std::ofstream ofs("output.txt"); boost::archive::xml_oarchive oa(ofs); // ファイル書き出し oa << (const FooData&)data; ofs.close(); }

  • boost::serializationについて

    次のコードがテンプレート辺りでコンパイルできません #include <list> #include <array> #include <fstream> #include <boost/serialization/serialization.hpp> #include <boost/serialization/array.hpp> #include <boost/serialization/list.hpp> #include <boost/archive/binary_iarchive.hpp> #include <boost/archive/binary_oarchive.hpp> std::list<std::array<bool, 3>> lab; std::array<bool, 3> pusharray; pusharray[0] = true; pusharray[1] = false; pusharray[2] = true; lab.push_back(pusharray); lab.push_back(pusharray); std::ofstream ofs("test"); boost::archive::binary_oarchive boa(ofs); boa << lab; ofs.close(); std::ifstream ifs("test"); boost::archive::binary_iarchive bia(ifs); bia >> lab; ifs.close(); エラーメッセージ: c:\program files\microsoft visual studio 10.0\vc\include\boost\archive\basic_binary_iprimitive.hpp(181): warning C4244: '引数' : 'std::streamsize' から 'size_t' への変換です。データが失われる可能性があります。 c:\program files\microsoft visual studio 10.0\vc\include\boost\archive\basic_binary_iprimitive.hpp(152): クラス テンプレート のメンバー関数 'void boost::archive::basic_binary_iprimitive<Archive,Elem,Tr>::load_binary(void *,size_t)' のコンパイル中 with [ Archive=boost::archive::naked_binary_iarchive, Elem=char, Tr=std::char_traits<char> ] c:\program files\microsoft visual studio 10.0\vc\include\boost\archive\detail\iserializer.hpp(362) : コンパイルされたクラスの テンプレート のインスタンス化 'void boost::archive::load_access::load_primitive<Archive,T>(Archive &,T &)' の参照を確認してください with [ Archive=boost::archive::naked_binary_iarchive, T=boost::archive::object_id_type ] (略) そもそもSTLコンテナのネストはserializeできないのでしょうか それともヘッダが足りないのでしょうか

  • boost::formatの値をstring型にコピーしたい

    boost::formatの値をstring型にコピーしたいのですが、うまくいきません。boost自体初めてで以下のサイトからダウンロードし、展開後VS2005のVCのインクルードフォルダーにboostフォルダーをまるまるコピーしただけですが・・・ http://sourceforge.net/project/showfiles.php?group_id=7586 boost 1.34.1 #include <iostream> #include <boost/format.hpp> using namespace std; using boost::format; void main(){ double x = 1.234; string str("abc"); //cout << format("%10.3f, [%16s]") % x % str << endl; // サンプルはこうでした。 // いったんstring型に入れて表示させたい。 string y; y = boost::format("%10.3f, [%16s]") % x % str; // エラー箇所 std::cout << y << std::endl; }

  • C++で継承元のクラスの代入演算子を呼び出す方法

    C++であるクラス継承したクラスの代入演算子で 継承元のクラスの代入演算子を呼び出す方法がわかりません。 こんな感じのソースです。 class T { T& operator=(const T &t) { } } class U :: T{ U& operator=(const U &u) { // ここでT.operator=()の代入演算を実行したい } } ((T)(*this)).operator=((T)(u))のようにキャストすればいけるかと思ったんですが、 コンパイルエラーでした。 よろしくお願いします。 また、これはプログラム上好ましくない手法でしたら、 別な実現方法をお教えください。

  • テンプレート関数に関して質問です。

    テンプレート関数に関して質問です。 wstringとstringに対して、似たような処理を行いたいので、template関数を使ってうまく定義できないかと思ったのですが、例えば、 #include<string> template<class T> void hoge(T &s){ s="a"; } void main(void){ std::string str; hoge(str); } の場合、class TがwstringだとL"a"としないといけないのですが、Tによってこれを変えることは可能でしょうか? また、できれば、hogeに想定外の変数を入れられたくないので、hogeをtypedefのようなのりで、 void foo(std::string &s); void foo(std::wstring &s); と定義しておきたいのですが何か良いアイデアはないでしょうか? 当然、hogeはstaticグローバル変数のように外部からはアクセスできないようにしておきたいのです。 よろしくお願いします。

  • clangで例外がキャッチできない?

    初質問です.yahooでも質問したのですがこちらでもしておきます. 趣味でプログラミングをしているものです.clang(コンパイラです)はエラーメッセージが分かりやすいので使っていたのですがg++と挙動が違うようです. 以下のソースのようにC++でboost::lexical_castを使おうとしたのですが,変換に失敗した際に,g++では例外をキャッチしてくれるのにclang(コンパイラです)ではキャッチしてくれず,実効停止してしまうようです.コンパイラオプションの問題でしょうか? ~ ソース test3.cpp ~ #include <iostream> #include <boost/lexical_cast.hpp> #include <string> using namespace std; int main() {     cout << "start" << endl; try { throw 10; // これはキャッチしてくれる } catch (int i) { cout << "thrown:" << i << endl; } cout << "and..." << endl; string str = "not a number"; try { int error = boost::lexical_cast<int>(str); } catch(boost::bad_lexical_cast& e) { // 以下,clangだと全部スルー? cout << "bad_lexical_cast!!" << endl; cout << e.what() << endl; } catch(exception& e) { cout << "exception!!" << endl; cout << e.what() << endl; } catch(...) { cout << "exception!?" << endl; cout << "error" << endl; } cout << "end" << endl; } ~ コンパイル&実行 ~ > clang test3.cpp -lstdc++ -I"C:\Program Files (x86)\boost\boost_1_47" > a.out start thrown:10 and... This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. > g++ test3.cpp -I"C:\Program Files (x86)\boost\boost_1_47" > a.exe start thrown:10 and... bad_lexical_cast!! bad lexical cast: source type value could not be interpreted as target end > ~ 環境 ~ OS:Windows 7 clang:version 3.1 g++(mingw):version 4.6.1(あ,でもインストール適当なんで4.7とかとかぶってるかもです) boost:version 1.4.7(1.0っていうんですかね?) 何か激しく勘違いをしている可能性もあるのでお暇な方はどうぞ教えてください. P.S. なんとインデントが消えてしまうのですね!

  • shared_ptr クラスについて

    shared_ptrクラスを使いたいのですが、使えません、どうしてでしょうか?ソースはこれです。 #include<iostream> #include <string> #include <fstream> #include<memory> using namespace std; class SMonster{ string name; int power; public: SMonster(); SMonster(int p); ~SMonster(){ }; void SetPower(int p); int GetPower(SMonster& t)const; void walk(const string& str); int GetPoint(void)const; }; class B {}; class D : public B {}; int main(void) { shared_ptr<D> sp0(new D); SMonster m(200); SMonster n(100); std::cout<<m.GetPower(m)<<std::endl; std::cout<<n.GetPower(n)<<std::endl; ShowWindow(10); }

  • c++プログラム。どこがだめか教えて欲しいです。

    以下のプログラムにおいて、後者のコンパイルが通りません。 違いは、クラス:Kurasu のコンストラクタに引数があるかないかで、 全部で3行違います。 後者のどこが問題か指摘して欲しいです。(さっぱりわからない…。) 試した環境は、 Visual C++ 2010 Express + インストーラー配布のboostと、 Eclipse 3.5.2 Galileo Windows 32bit ベース / Pleiades All in One 3.5.2.20100226 のUltimate+←を使ってソースをビルドしたboostです。 boostのバージョンは、1.46.1です。 -------------------------------------------------- #include <iostream> #include <boost/thread.hpp> using namespace std; using namespace boost; class Kurasu { public: Kurasu(int ababa){}; void run(){ for( int i = 0; i < 10; i++ ){ cout <<"foo "; } }; }; int main() { cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!! Kurasu hoge(1); Kurasu piyo(2); thread thr_hoge( &Kurasu::run, &hoge ); thread thr_piyo( &Kurasu::run, &piyo ); thr_hoge.join(); thr_piyo.join(); return 0; } -------------------------------------------------- #include <iostream> #include <boost/thread.hpp> using namespace std; using namespace boost; class Kurasu { public: Kurasu(){}; void run(){ for( int i = 0; i < 10; i++ ){ cout <<"foo "; } }; }; int main() { cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!! Kurasu hoge(); Kurasu piyo(); thread thr_hoge( &Kurasu::run, &hoge ); thread thr_piyo( &Kurasu::run, &piyo ); thr_hoge.join(); thr_piyo.join(); return 0; } --------------------------------------------------

専門家に質問してみよう