• 締切済み

仮想基底クラスをもつクラスの代入演算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 さんのコピーコンストラクタでコピー代入を実装する方法の方がいいのかとも思います。 みなさん、どう思われますか? また、そのほかに、効果的なテクニックがあれば、ぜひ、ご教示ください。

みんなの回答

noname#38642
noname#38642
回答No.1

これが一番いいということで^^

関連するQ&A

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

    仮想基底クラスをもつクラスの代入演算で、仮想基底クラスの代入が各々のサブオブジェクトにつきただ一回なされるようにしたい場合に、みなさん、どのように設計されていますか? 何か、手軽なテクニックがあれば、ご教示ください。 ===(コンストラクタなどは略、アクセス制御も略) たとえば、 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 が正解なんでしょうけど^^

  • 代入演算子?

    すいません、自分の調べ方が悪いのだとは思いますが、 出てこないので意味を教えてください。 if (100 <= $z) { $this->_s_A1 = 3000; } Trueだった場合の、「$this->_」(ハイフンも含む)の意味が良く分からないのです。 配列の代入だったかなあ?と思ったのですが…正確にわかっていません。

    • ベストアンサー
    • PHP
  • 派生クラスのメンバを基底クラスの参照に代入(C++

    文末のコードのように、 基底クラスで、派生クラスのメンバの参照を持つのはまずいでしょうか。 (classではなくstructにしているのは質問上でのpublic:の省略のためだけです) 初期化順序的には、基底クラスの参照先は、 基底クラスのコンストラクタが走る時点で初期化されていないので、 コンストラクタ内で参照に対して何かしようとすると問題になると思っています。 基底クラスのコンストラクタ内で派生クラスメンバの参照に対して何かしなければ、 参照は有効で、派生クラスのコンストラクタ実行後であれば 問題なく動くと思ってよいでしょうか。 struct A { int& m_ref; A(int& ref) : m_ref(ref) { } }; struct B : public A { int m_obj; B() : A(m_obj) { } };

  • 構造体の要素すべてに対する四則演算の方法を教えてください.

    構造体の要素すべてに対する四則演算の方法を教えてください. たとえば、 2点a,bの座標成分x,y,zをそれぞれの座標ごとに足す方法を教えてください. 下のようにx,y,z成分を持ったa,bがあります。 struct point{ int x; int y; int z; }; struct point a; struct point b; struct point c; この場合, c=a+b; と書くことができず, それぞれの成分ごとに以下のように足さなくてはなりません. c.x=a.x+b.x; c.y=a.y+b.y; c.z=a.z+b.z; この方法でできるのですが, 非常に効率的でないのでなにかもっと簡単に記述する方法を教えてください. お願いいたします.

  • C# こういう場合ってどうなるの?

    public void A(bool b) {   if(b ? B() : C())//分かると思いますが、三項演算子   {     //略   } } public bool B() {   return true; } public bool C() {   return false } 上記のAにtrueを渡し実行した場合、 if文の中はどうなるのでしょうか? 引数がtrueならBを実行し、Bの戻り値trueが if文で処理され、if内に入る・・・でよろしいのでしょうか? それとも引数bの評価がそのままifで使われるのでしょうか? 例えばのコードなので、bだろうがBだろうが変わらない・・・みたいな 回答はご遠慮ください。

  • basic_ostreamクラスについて

    http://msdn.microsoft.com/ja-jp/library/k262esc6.aspx をみると、VC++2010のbasic_ostream::sentryには  operator bool( ) const; がある事になっていますが、実際は無いようです。 VC++2010 Express Edition のostream(C:\Program Files\Microsoft Visual Studio 10.0\VC\include\ostream)を見ると、sentryにoperator bool() constがありませんでした。 代わりに __CLR_OR_THIS_CALL _OPERATOR_BOOL() const { // test if stream state okay return (_Ok ? _CONVERTIBLE_TO_TRUE : 0); } というのがありますが、 #define _STD ::std:: #define _OPERATOR_BOOL operator _STD _Bool_type と定義されており、operator bool( ) constとは別物でした。 このため、basic_ostream::sentry::operator bool( )を使用しているソースをVC++2010(Express Edition)でビルドしようとするとエラーになります。 ちなみに、このソースをVC++2008 Express Editionでビルドすると通ります。 質問なのですが、 1)basic_ostream::sentry::operator bool( )を使うソースをVC++2010 Express Editionでビルドするにはどうすれば良いでしょうか? 2)なぜVC++2010 Express Editionからbasic_ostream::sentry::operator bool( )がなくなってしまったのでしょうか? ご存知の方、ご教授ください。 よろしくお願いします。

  • c++について

    入力した値が123または456で一致したら一致と表示したいのですがどうfor文を回すか分かりません。 ご助力願います_(._.)_ class N { bool hit(const char* a[],const char* b) {   for(int i=0;i<*a[i];i++) if(*a[i]!=b[i]) { return false; } return true ; } public: N() { const char* a[ ]={ "123","456"}; char b[4]; int num; cin>>num; sprintf_s(b, 4, "%03d", num); if(hit(a,b)) cout<<"一致"; else cout<<"不一致"; } };

  • 基底

    a=(0,1,1) b=(1,0,1) c=(1,1,0) である。X=t(x,y,z)の、基底a,b,cに対する座標ベクトルを求めてくださいお願いします。(ちなみにt()は転置行列を表しています)

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

    文字列クラスを作りたいと思っています。 以下のようなところまでは作れましたが、 エラーがでてしまいます。 どこかおかしいところがあるのでしょうか? *********************************************** #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; } ***********************************************

  • 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) { } 上記のプログラムだと、下に書いてある代入演算子は問題ありません。 なぜこうなるんでしょうか? ご教授お願いします。

専門家に質問してみよう