• ベストアンサー

std::stringの継承

#include <iostream> #include <string> class test : public std::string{ }; int main() { test tmp; tmp = "aaa"; } tmp = "aaa";ですが test::operator =(char *) が定義されていないとでますが何故なんでしょうか? string(basic_string)でoperator=が定義されていると思うのですが、 演算子の定義は継承されないのでしょうか。

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

  • ベストアンサー
回答No.1

結論から言ってしまえば、class test に、char * を引数とするコンストラクタがないからです。 「演算子」というくくりでは、普通は継承されます。例えば、 test tmp1; test tmp2; に対して、 tmp1 == tmp2 という比較は、文法上有効です。 さて、operator=() は、例外で、ユーザーが明示的に定義しない場合、まず、暗黙の型変換(char * → test)をしようとします。 これは具体的には、test::test(char *) というコンストラクタの呼び出しになります。 が、test::test(char *) が存在しないため、代入もできないというメカニズムのようです。

furyfox
質問者

お礼

ご回答有り難うございます。 おっしゃる通りコピーコンストラクタを用意するとコンパイルが通るようになりました。

その他の回答 (5)

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

> SGI STLには含まるんですよね? 確かにバージョン3.1ぐらいからSGIのSTLにもbasic_stringが入っていますね。標準C++に導入されたころのSTLにはまだ入ってなかったはずです(というより、標準C++のものをSTLにバックポートした)。ISO/IEC 14882の中にはSTLとかStandard Template Libraryという言葉は出てこないので、単にSTLといえばSGIのものを指すと考える方が妥当なのかもしれません。そうであれば、basic_stringはSTLに含まれるという結論になるかと思います。 とはいえ、実際にSGIのSTLを使っている人は率からいうとそんなにないわけですし、普通は標準C++ライブラリの一部と考えるのが妥当ではないでしょうか。 この辺はちょっと微妙ですね。 > std::vectorやstd::listはSTLですよね?? こちらは間違いなくSTLです。

furyfox
質問者

お礼

わざわざお答えくださり有り難うございました。

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

> STLは奥が深い。。。 いや、basic_stringはSTLではありません。

furyfox
質問者

お礼

ご指摘有り難うございます。 SGI STLには含まるんですよね? http://www.sgi.com/tech/stl/basic_string.html std::vectorやstd::listはSTLですよね?? 質問内容がそれてしまいましたが、もしよければお答え頂けないでしょうか。

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

直接の原因は、testクラスに変換コンストラクタまたは代入演算子が定義されていないところにあります。 あと、#3の方の意見とも関連するのですが... basic_stringはpublic継承には余り適していません。継承で解決するより、テンプレート引数のtraitsやAllocatorを摩り替える方がよいでしょう。振る舞いを変えるのではなく、インタフェースを追加するのであれば、メンバ関数としてより、フリー関数(非メンバ関数)にした方がよいでしょう。

furyfox
質問者

お礼

traits:その存在をはじめて知りました。そんなものが指定できたのですね。 STLは奥が深い。。。

回答No.3

直接の回答ではないのですが…… string を継承するというのがちょっと気になりまして。 ご質問の内容が、単純に興味からであれば別ですが、string を継承する必要があるとお感じだとしたら、それは、設計を間違っているのかも知れません。 (そういうケースが多いのです) string の継承は、例えば、データをすべて小文字として扱う string とか、数字しか受け付けない string とか、10文字以上は受付けない(適切に処理する) string とか、いずれも、……という string を定義するものです。 こういう用途であれば問題ありません。 よくある間違いは、本来、class のメンバーとして string を持つべきものでも、string を継承させようとするものです。 string を継承すべきなのか、string メンバーを持てばいいのか、そのあたりご検討を。 既に、ご検討済みであれば失礼しました。

参考URL:
http://www.cmagazine.jp/src/kinjite/cpp/idea.html#index36
furyfox
質問者

お礼

そういったコーディングを実際しているわけではなく、 あくまで興味の質問でしたがご意見勉強になりました。

  • nk2
  • ベストアンサー率23% (6/26)
回答No.2

operator=は特殊で継承されません。 これを回避するためのテクニックは string& test::operator=(const char* T) { /*test独自のコピー処理をここに記述*/ return string::operator=(T); } string& test::operator=(const string& T) { /*test独自のコピー処理をここに記述*/ return string::operator=(T); } string& test::operator=(const char T) { /*test独自のコピー処理をここに記述*/ return string::operator=(T); } を宣言することです。 operator=が継承されない理由としては string::operatorでは 追加されたメンバがコピーされないためです。 なお派生クラスには親クラスのオブジェクトが代入可能なので上のコードは有効です。

furyfox
質問者

お礼

ご回答有り難うございます。大変参考になりました。

関連するQ&A