March 14, 2008operator=()と継承[Computer]
拙作のC++行列ライブラリmatrix.hのメンテナンスを久しぶりにやってみているのですが、部分行列の代入の解釈で少し考えることがありました。簡易的なコードで書くと以下のような問題です。 Matrix m1, m2;
m.partialMatrix = m2; このとき部分行列への代入は、元の行列の書き換えもおこなうべき(上の例でいうとm1も変更されて然るべき)であると思います。現在の実装では行列を構成する要素データ、そして行列という箱、これら2つを別々に管理するフライウェイトパターンを用いていました。そのため代入については要素ごとの代入を行わず中身全体をつけかえる動作をしており、上記のような元の行列まで書き換えるということを想定していませんでした。 そこで部分行列を適当な子クラスで表現し、子クラスで代入演算子のオーバーロードを行うことによって、上記の問題の解決をはかろうとしました。つまり部分行列への代入は要素ごとの代入を行う一方、それ以外の行列では要素をまとめて付け替えるだけというフライウェイトパターンの共存を目指しました。 前置きがながくなってしまいましたが、ここで表題にあるとおりの代入演算子の問題に引っかかりました。どうも代入演算子を継承先でオーバーロードした際、そのオーバーライド(言葉がややこしいですね、笑)が通常の関数と異なるようなのです。違いを明らかにするため、検証用のプログラムoperator_equal_test.cppを書いてみました。要約をすると問題が生じるのは以下のようなケースでした。 class A {
public: A(){} virtual ~A() {} self_t &operator=(const A &a){ cout << "A::operator=(A)"; return *this; } }; class B : public A { int main(){ cout << "a = a => "; a = a; cout << endl; // (1) return 0; さて結果はどうなるでしょうか。(1)、(2)ではAが左辺オペランド、(3)、(4)ではBが左辺オペランドなので通常の関数と同様に考えるのであれば、(1)、(2)ではA::operator=(A)が、(3)、(4)ではB::operator=(A)が呼び出されそうなものです。しかし(4)では意表をついてA::operator=(A)が呼ばれます。VC2005/2008 Express Edition、gcc 3.4.4で試して同一の結果がでたので、おそらくC++の仕様でないかと思います(現在調査中ですが、ご存知でしたら是非お教えください)。なお(4)のケースでA::operator=(A)を呼ばれないようにするためには、B::operator=(B)なる関数を定義する必要がありました。もし、さらに深い継承関係がある場合には、親クラス::operator=(親クラス)で子クラス=子クラスを捕捉することも可能です。 以上のような検証の末、できあがったのが行列ライブラリmatrix.h(1.28)です。まだまだ改良の余地がありそうですが、よろしければ使ってみてください。 コメント
どうもご無沙汰です。ベンチプレスが挙がらなくなったホークスファンです。(わかるかな) さて本題ですが、これはシンプルに B::operator=(B) が自動で生成されて、そのなかで A::operator=(A) が呼ばれているのではないかと思いました。 では仕事にもどるとします。 Posted by: soleus : April 11, 2008 03:18 PM>soleusさん、改めTさん 代入演算子のオーバーロードについて調べていて辿り着きました。 以上、気になりましたのでコメントしました。 Posted by: 通りすがり : February 24, 2009 12:22 PM>通りすがりさん こちらにアップされているサンプルコードを見てみました。 >通りすがりさん なるほど。 もうお気付きのようですが、 サンプルコードでは、たまたまA::operator=(A)のみオーバーロードしていたため、こちらに気付いただけで、fenrirさんの感覚が特にずれているわけではありません。B::operator=(B)もちゃんと呼ばれています^^ ちなみにB::operator=(A)は自動で作られないので、自分で定義しない限り呼ばれません。 少々くどい説明になってしまい申し訳ありません(汗) コメントする
|
検索君
スポンサード リンク
最近の記事 HDL-AAX2 シャットダウンスクリプ… 曜日を求める(8bit範囲で) Assisted GPS (A-GPS)… HDL-AAX2の修理 ExcelでMarkdownの表を編集 Rubyで確率分布の性質を求めるgem Windowsのcygwin/MSYS2… RubyでGPS姿勢推定 RubyでGPS受信機 boost::math::distrib… E-MailRelay本体更新(ver … RinRuby (Ruby gem fo… RSpecでのexample間共用のイン… 夏休みの工作: ソースコード公開 夏休みの工作: タッチセンサ GPD Pocketに増設したストレージ… GPD Pocketにストレージ増設 GPD Pocket 内蔵USBハブ基板… GPD Pocket 内蔵USBハブ基板 久しぶりの基板作成 自転車用六角穴付き特注ナット Xiaomi Mi Max (Hydro… Xiaomi Redmi Note 3 … Super Sylphide 進捗状況(… Super Sylphide 進捗状況(… かてごり~一覧 Aero & Astro (100) Computer (189) Embedded System (308) Info (14) Mountain (43) Movable Type (28) Movie & Animation (20) Music (9) Photo (47) Site Management (46) Timely (135) Tips (68) 今月かれんだ~ あ~かいぶ 最近のTrackback ダイナミックDNS 3domain.hk… @ 3年落ちのPCでまだまだがんばる日記 9X到着〜インプレ@ 艦船プラモとRCマイクロヘリが好き! USL-5P@ 谷岡のページ (PukiWiki/TrackBack 0.3) [mbed][猫カメラ]猫カメラつづき@ Embedded 脇見運転 [mbed][猫カメラ]mbed + 猫…@ Embedded 脇見運転 MT4 @ ダイナミックで動く画像リサイ…@ wed@ 私がAudionoではなくBlackfi…@ Blackfin空挺団::Blog 【Web】はぐれメタルできたよー@ I'm St'a'dying English ちっとも、作っていない@ 三D坊主 猫カメラ@ 脇見運転 To 『猫カメラ』 試作中 最近のこめんと いきなりのコメント申し訳ありません。
… by まろまろ先輩 @ GPD Pocket 内蔵USBハブ基板 音楽を読み取りする 説明して欲しいですby 榎本待子 @ iPodからPCに曲を転送 Arduino嫌いだわ。
あんなもの見…by Alice @ 僕がArduinoを使わないわけ やや遅い書き込みで失礼します。
別の機…by LOSスマホ @ Xiaomi Mi Max (Hydrogen) の MIUI8 FM Radio (stock) 日本バンド対応 >Bさま
確か当時、そこまで高くなかっ…by fenrir @ MKS Promenade-Ezy ケージ交換 お値段はおいくらでしたか?
私も曲げて…by Bさま @ MKS Promenade-Ezy ケージ交換 >forester3さん
お返事遅くな…by fenrir @ EZUSB Keilからsdccへ、EZUSB.lib等の移植 お世話になります。3年ほど前sdccの…by forester3 @ EZUSB Keilからsdccへ、EZUSB.lib等の移植 以下のものはどうですかねby て @ VBAで泣かないために >tomi9さん
コメント気づくのが遅…by fenrir @ TCM8240MD breakout (i2cで画像取得モジュール) 動作確認完了 りんく集 |