ページ 11

演算子多重定義が必要な理由

Posted: 2015年8月14日(金) 14:12
by 23120b
ベクトルを使った下記サンプルコードで演算子オーバーロード(11,17,22行目)が必要な理由が分かりません。
どなたかご教授頂けないでしょうか。よろしくお願いします。
オーバーロードしなくてもビルドは通っています。

コード:

// ベクトルにクラスオブジェクトを保存する
#include <iostream>
#include <vector>
using namespace std;

class Demo {
  double d;
public:
  Demo() { d = 0.0; }
  Demo(double x) { d = x; }
  Demo &operator=(double x) {
    d = x; return *this;
  }
  double getd() { return d; }
};

bool operator<(Demo a, Demo b)
{
  return a.getd() < b.getd();
}

bool operator==(Demo a, Demo b)
{
  return a.getd() == b.getd();
}

int main()
{
  vector<Demo> v;
  int i;

  for(i=0; i<10; i++)
    v.push_back(Demo(i/3.0));

  for(i=0; i<v.size(); i++)
    cout << v[i].getd() << " ";

  cout << endl;

  for(i=0; i<v.size(); i++)
    v[i] = v[i].getd() * 2.1;

  for(i=0; i<v.size(); i++)
    cout << v[i].getd() << " ";

  cout << endl;

  return 0;
}

Re: 演算子多重定義が必要な理由

Posted: 2015年8月14日(金) 14:19
by みけCAT
23120b さんが書きました:ベクトルを使った下記サンプルコードで演算子オーバーロード(11,17,22行目)が必要な理由が分かりません。
他のサンプルコードでは必要かもしれませんが、確かにこのサンプルコードでは必要ないですね。
YAGNI原則に基づき、消してもいいかもしれません。

コード:

// ベクトルにクラスオブジェクトを保存する
#include <iostream>
#include <vector>
using namespace std;

class Demo {
  double d;
public:
  Demo() { d = 0.0; }
  Demo(double x) { d = x; }
  double getd() { return d; }
};

int main()
{
  vector<Demo> v;
  int i;

  for(i=0; i<10; i++)
    v.push_back(Demo(i/3.0));

  for(i=0; i<v.size(); i++)
    cout << v[i].getd() << " ";

  cout << endl;

  for(i=0; i<v.size(); i++)
    v[i] = v[i].getd() * 2.1;

  for(i=0; i<v.size(); i++)
    cout << v[i].getd() << " ";

  cout << endl;

  return 0;
}
オフトピック
i<v.size()のところで、comparison between signed and unsigned integer expressionsっていう警告が出るなあ。

Re: 演算子多重定義が必要な理由

Posted: 2015年8月14日(金) 14:25
by みけCAT
この場合見かけの動作は変わらないですが、代入演算子のオーバーロードがあるときと無いときでは内部の動作が異なります。
どの関数が呼ばれたかをわかるようにすると、違いがわかります。
ちなみに比較演算子2個は、このコードでは全く動作に関係無いようですね。

オーバーロードあり

コード:

// ベクトルにクラスオブジェクトを保存する
#include <iostream>
#include <vector>
using namespace std;

class Demo {
  double d;
public:
  Demo() { d = 0.0; }
  Demo(double x) { 
    cout << "constructed : " << x << endl;
    d = x; 
  }
  Demo &operator=(double x) {
    cout << "assigned : " << x << endl;
    d = x; return *this;
  }
  double getd() { return d; }
};

bool operator<(Demo a, Demo b)
{
  cout << "lt? " << a.getd() << " and " << b.getd() << endl;
  return a.getd() < b.getd();
}
 
bool operator==(Demo a, Demo b)
{
  cout << "equal? " << a.getd() << " and " << b.getd() << endl;
  return a.getd() == b.getd();
}

int main()
{
  vector<Demo> v;
  int i;

  for(i=0; i<10; i++)
    v.push_back(Demo(i/3.0));

  for(i=0; i<v.size(); i++)
    cout << v[i].getd() << " ";

  cout << endl;

  for(i=0; i<v.size(); i++)
    v[i] = v[i].getd() * 2.1;

  for(i=0; i<v.size(); i++)
    cout << v[i].getd() << " ";

  cout << endl;

  return 0;
}
実行結果

コード:

constructed : 0
constructed : 0.333333
constructed : 0.666667
constructed : 1
constructed : 1.33333
constructed : 1.66667
constructed : 2
constructed : 2.33333
constructed : 2.66667
constructed : 3
0 0.333333 0.666667 1 1.33333 1.66667 2 2.33333 2.66667 3 
assigned : 0
assigned : 0.7
assigned : 1.4
assigned : 2.1
assigned : 2.8
assigned : 3.5
assigned : 4.2
assigned : 4.9
assigned : 5.6
assigned : 6.3
0 0.7 1.4 2.1 2.8 3.5 4.2 4.9 5.6 6.3 
オーバーロードなし

コード:

// ベクトルにクラスオブジェクトを保存する
#include <iostream>
#include <vector>
using namespace std;

class Demo {
  double d;
public:
  Demo() { d = 0.0; }
  Demo(double x) { 
    cout << "constructed : " << x << endl;
    d = x; 
  }
  double getd() { return d; }
};

int main()
{
  vector<Demo> v;
  int i;

  for(i=0; i<10; i++)
    v.push_back(Demo(i/3.0));

  for(i=0; i<v.size(); i++)
    cout << v[i].getd() << " ";

  cout << endl;

  for(i=0; i<v.size(); i++)
    v[i] = v[i].getd() * 2.1;

  for(i=0; i<v.size(); i++)
    cout << v[i].getd() << " ";

  cout << endl;

  return 0;
}
実行結果

コード:

constructed : 0
constructed : 0.333333
constructed : 0.666667
constructed : 1
constructed : 1.33333
constructed : 1.66667
constructed : 2
constructed : 2.33333
constructed : 2.66667
constructed : 3
0 0.333333 0.666667 1 1.33333 1.66667 2 2.33333 2.66667 3 
constructed : 0
constructed : 0.7
constructed : 1.4
constructed : 2.1
constructed : 2.8
constructed : 3.5
constructed : 4.2
constructed : 4.9
constructed : 5.6
constructed : 6.3
0 0.7 1.4 2.1 2.8 3.5 4.2 4.9 5.6 6.3