• ベストアンサー

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

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

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

  • ベストアンサー
  • txrx
  • ベストアンサー率45% (83/184)
回答No.2

return T::operator=(u); //ここで ↑の位置に上記を記述します。 つまりアクセス指定を基本クラスにして、operator関数を直接記述します。

terra5
質問者

お礼

うまくいきました。 それとキャストは不要でした。 ありがとうございました。

その他の回答 (3)

noname#30727
noname#30727
回答No.4

たまたま見てしまったので・・・ #2さんの >return T::operator=(u); アップキャストは自動的に行われるから、この場合の引数にはキャストは不要で、T&をreturnするにはダウンキャスト無しには無理だから、戻り値は捨てた方が良さそうです。 T::operator=(u); //のこりの処理 return *this;

terra5
質問者

お礼

補足ありがとうございました。 既に、#2の回答でこの回答と同じ事をやってますが、 回答がある安心できます。

  • txrx
  • ベストアンサー率45% (83/184)
回答No.3

#2です。 ごめんなさい、間違ってます。 引数も基本クラスにあわせるようにキャストしてください。

  • 12m24
  • ベストアンサー率23% (193/817)
回答No.1

 なんか不自然ですが。 ・継承の記述  クラスParentからクラスChildに継承する場合、はじめのクラスの宣言で class Child : public Parent {//うんぬん } の様に、セミコロンひとつで区切ります。 ・publicなどの未記入  具体的な動作はコンパイラごとに異なりますが、public, protected, privateの記入をしなかった場合、多くのコンパイラはprivateで宣言されたものとして扱います。private宣言されたものは継承できませんので、publicまたはprotectedを記入してください。

terra5
質問者

補足

簡単なサンプル書こうとして、抜かしてしまいました。 細かいチェック恐れ入ります。

関連するQ&A

  • operator代入演算子のやり方で疑問が

    C++の勉強をしています。 そこでoperatorを使うことをやっているんですが、この演算子、引数を二つつけるとエラーになります。クラス内で定義するとこうなります。 ですがグローバルで定義するとエラーが出力されません。 何故なんでしょうか? 戻り値の関係でしょうか?  class Complex { public: Complex() { } public: // これはエラー、この演算子関数のパラメータが多すぎますと出力される const Complex operator+(const Complex x, const Complex y) { } }; // これはでない・・・ const Complex operator+(const Complex x, const Complex y) { } 上記のプログラムだと、下に書いてある代入演算子は問題ありません。 なぜこうなるんでしょうか? ご教授お願いします。

  • 仮想基底クラスをもつクラスの代入演算2

    <仮想基底クラスをもつクラスの代入演算>の続きですが、結局、assign のようなものを作って、以下のように書くのが一番いいのでしょうか。。。 ====(一応、自己代入も考慮して書くと^^) #include <algorithm> struct X { int x; X &assign(const X &z, bool top) { if (this != &z) x = z.x; return *this; } X &operator=(const X &z) { return assign(z, true); } }; struct A : virtual X { int a; A &assign(const A &z, bool top) { if (this != &z) { if (top) X::assign(z, false); a = z.a; } return *this; } A &operator=(const A &z) { return assign(z, true); } }; struct B : virtual X { int b; B &assign(const B &z, bool top) { if (this != &z) { if (top) X::assign(z, false); b = z.b; } return *this; } B &operator=(const B &z) { return assign(z, true); } }; struct C : A, B { int c; C &assign(const C &z, bool top) { if (this != &z) { if (top) X::assign(z, false); A::assign(z, false); B::assign(z, false); c = z.c; } return *this; } C &operator=(const C &z) { return assign(z, true); } }; ==== ただ、<仮想基底クラスをもつクラスの代入演算>で、jacta さんが提示してくださった方法も、処理量は増えますが、アロケートする必要があるポインタなどのデータメンバのアロケートやデリートする処理コードをコンストラクタに集中できるので、「コーディング量の減少・改変の際の修正し忘れの可能性を低くできる」というメリットがあると思います。ハンドルクラスやコンテナクラスを実装する際は、swap() 機能が必要となると考えられるので、jacta さんのコピーコンストラクタでコピー代入を実装する方法の方がいいのかとも思います。 みなさん、どう思われますか? また、そのほかに、効果的なテクニックがあれば、ぜひ、ご教示ください。

  • 仮想基底クラスをもつクラスの代入演算

    仮想基底クラスをもつクラスの代入演算で、仮想基底クラスの代入が各々のサブオブジェクトにつきただ一回なされるようにしたい場合に、みなさん、どのように設計されていますか? 何か、手軽なテクニックがあれば、ご教示ください。 ===(コンストラクタなどは略、アクセス制御も略) たとえば、 struct X { int x; }; struct A : virtual X { int a; }; struct B : virtual X { int b; }; struct C : A, B { int c; }; int main() { C c1, c2; c1 = c2; } として、デフォルト代入に頼ると、c1.x への c2.x の代入を複数回行うコンパイラが多いですよね(というか、きっちり1回のみ行うようにしているコンパイラに出会ったことがない)。C++標準でも、初期化はただ一度とコンパイラが保証するようになっていますが、代入は何度代入してもいいようになっていたと思います。 以下のように、各クラスで、直接の非仮想基底クラスと自身のデータメンバにのみ代入するメンバ関数を定義して、最派生クラスでのみ、仮想基底クラスの代入を行うのが、普通のやり方なんでしょうか。 これでもいいのですが、後に、ある基底クラスに仮想クラスが付け加わったりすると、その基底クラスから派生しているクラスの代入演算の定義をすべていじらないといけなくなるので、もっといいテクニックがあるのなら、と思いまして質問したしだいです。 struct X { int x; X &nvAssign(const X &z) { x = z.x; return *this; } X &operator=(const X &z) { nvAssign(z); } }; struct A : virtual X { int a; A &nvAssign(const A &z) { a = z.a; return *this; } A &operator=(const A &z) { X::nvAssign(z); return nvAssign(z); } }; struct B : virtual X { int b; B &nvAssign(const B &z) { b = z.b; return *this; } B &operator=(const B &z) { X::nvAssign(z); return nvAssign(z); } }; struct C : A, B { int c; C &nvAssign(const C &z) { A::nvAssign(z); B::nvAssign(z); c = z.c; return *this; } C &operator=(const C &z) { X::nvAssign(z); return nvAssign(z); } }; === 1. 仮想基底クラスは何度代入されてもいいようにするもんだ。 2. 仮想基底クラスにデータメンバを持たせるのは間違いだ。 3. 遅くなるから、そもそも仮想基底クラスなど使わない。 という回答は無しでお願いいたします。たぶん、1 か 2 が正解なんでしょうけど^^

  • c# 継承元についての疑問

    こんにちは、c# 初心者です。 現在クラスの継承で、どのクラスから継承させるかで悩んでいます。  具体的にはSampleBase<T>という抽象クラスがあり、そこからSampleA<T>とSampleB<T>に派生しています。  ここまでは問題ないのですが、SampleA<T, TSub>とSampleB<T, Sub>のクラスも同様に作ります。  これらのクラスは「SampleBase<T>から継承させたSampleBase<T, TSub>というクラスを作り、ここから継承させたほうがよい」か、「SampleBase<T, TSub>なんて作らないで、それぞれSampleA<T>とSampleB<T>から継承させたほうがよい」かそれともで悩んでいます。 ------------------------------ SampleBase<T>  ┣SampleA<T>  ┣SampleB<T>  ┗SampleBase<T, TSub>    ┣SampleA<T, TSub>    ┗SampleB<T, TSub> ------------------------------ か ------------------------------ SampleBase<T>  ┣SampleA<T>  ┃ ┗SampleA<T, Sub>  ┗SampleB<T>    ┗SsampleB<T, Sub> ------------------------------  単に型変換を可能にするだけならキャストをオーバーライドすればよいのですが、as演算子、is演算子はそうはいかないので悩んでいます。  コードの量を減らすのと、is、as演算子に完全に対応できるようにするのなら後者のほうが良いのですが、そうするとSampleBase<T>のコードがどんどん嵩張っていくのであまりいい気がしません。  かといって、前者ならis, as演算子がうまく使えません。  どなたか詳しい方がいらっしゃいましたら教えてください。

  • オーバーライドされた演算子の継承

    オーバーライドされた演算子は継承されますか? 今やろうとしていることは、変換演算子を継承しようとしています。 試してみたところ警告もなく出来ましたが、この動作は規格上正しいのでしょうか? #include <iostream> class base { public: operator bool() { return true; } }; class derived : public base { }; int main() { derived d; if(d) { std::cout << "true"; } }

  • 自分で作ったクラスを継承するとエラーが出ます。

    サーブレットを勉強しているのですが、自分で作成したクラスを継承した サーブレットを作成してコンパイルするとその継承したクラスの シンボルを解釈できませんというエラーが出ます。 たとえばclass01というクラスを継承したclass02.javaをコンパイルすると シンボルを解釈できません public class02 extends class01{ といったエラーが出てしまいます。 どうも自分で作ったクラスを読み込めていないようなのですが どうしたらよいのでしょうか? 初歩的な質問かもしれませんが、よろしくお願いします。 ちなみにOSはWin2000、サーブレットはJRUNを使用しています。

    • ベストアンサー
    • Java
  • 継承したクラスを、継承元のクラス型の引数に渡すとどうなるのでしょうか?

    継承したクラスを、継承元のクラス型の引数に渡すとどうなるのでしょうか? 以下のようなケースで、 #include "stdio.h" using namespace std; // baseクラス class base { private:  int m_nII;  int m_nJJ;  int m_nKK; public:  base(int i,int j,int k){ m_nII=i; m_nJJ=j; m_nKK=k; }  int GetSum(){ return (m_nII+m_nJJ+m_nKK); } }; // base 継承クラス class hoge : public base { public:  hoge() : base(1,2,3){} }; void func(base* obj){ // baseクラスを引数に取る関数  printf("sum is %d\n", obj->GetSum()); } // main int main(){  hoge objHoge;  func((base*)&objHoge); // <-キャストして渡す  return 0; } として、一応、gccでコンパイルは通り、実行結果も期待通りだったのですが、 このやり方で問題は無いのでしょうか? (たとえば継承先のクラスが独自のメンバを持っていたりなどした場合、期待した結果にならないとか・・) よろしくお願いします。

  • 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; } どなたか答えて頂けると有難いです。

  • c++のnew演算子をオーバーロードできるものの、

    c++のnew演算子をオーバーロードできるものの、 delete演算子をオーバーロードできなくて悩んでいます。 コンパイルは通るのですが、ランタイム時に ペアとなるdeleteが呼ばれません。 inline void* operator new(size_t size, const char* filename , int line , const char* funcname ) { return my_local_malloc( size , filename , line , funcname ); } inline void operator delete(void* pMem, const char* filename , int line , const char* funcname ) { my_local_free( pMem , filename , line , funcname ); } deleteも確実にオーバーロードできる方法を ご存知のかた、お教え願います。

  • C++テンプレートクラスの内部クラスについて

    テンプレートクラスについていろいろ試していたところ以下のようなコードで struct A {     struct AA { };     operator A::AA() { return A::AA(); } // (1) }; template<typename T> struct B {     struct BB { };     template<typename U>     operator B<U>() { return B<U>(); } // (2)     template<typename U>     operator typename B<U>::BB() { return typename B<U>::BB(); } // (3) }; int main() {     static_cast<A::AA>(A()); // (1) ok     static_cast<B<int> >(B<short>()); // (2) ok     static_cast<B<int>::BB>(B<short>()); // (3) compile error     return 0; } (1)と(2)はできて(3)だけがコンパイルを通りませんでした。 試したコンパイラはVC9とg++(3.3.4)とbcc32(5.5.1)で、VC9では以下のようなエラーをはきました。 「error C2440: 'static_cast' : 'B<T>' から 'B<T>::BB' に変換できません。     with [ T=short ] and [ T=int ] コンストラクタはソース型を持てません、またはコンストラクタのオーバーロードの解決があいまいです。」 (1)と(2)ができれば(3)のようなこともできそうな感じがしたのですが、他に書き方があるのでしょうか。 どなたかご存知の方がいらっしゃいましたらご教示お願いします。

専門家に質問してみよう