ためになるホームページ お問い合わせ




TOP > C++ > 演算子のオーバーロード
演算子のオーバーロード
C++では、演算子をオーバーロードする事ができる。
オペレータをオーバーロードするには、operatorキーワードを使って演算子を定義する。
void operator+(...);

単項演算子のオーバーロード
単項演算子のオーバーロードは、単項演算子の右辺にあるオブジェクトが引数として渡される。
例えば、obj1 = obj2;
という式がある時、「=」をオーバーロードした時は、
obj1.=(obj2);の意味となる。
(注意)後置型インクリメント・デクリメントは、引数にint型をとるようにする。(実際には受け取らないが、ダミーで宣言する)

単項演算子のオーバーロードの例
#include <iostream>

class TEST
{
private:
  int m_data_;
public:
  TEST(int data) :m_data_(data)
  {
  };
  ~TEST(){};
  //データのセット
  void setData(int data)
  {
    m_data_ = data;
  }

  int print()
  {
    return(m_data_);
  }

  //単項演算子のオーバーロード
  TEST& operator=(const TEST &obj)
  {
    m_data_ = obj.m_data_;
    return(*this);
  }

  void operator++(int)
  {
    m_data_++;
    return;
  }
  void operator--()
  {
    --m_data_;
    return;
  }
  TEST* operator->()
  {
    return(this);
  }
};

int main(int argc, char** argv)
{
  TEST obj1(2);
  TEST obj2(3);

  obj1 = obj2;
  std::cout << "ope= m_data_ = " << obj1.print() << std::endl;
  obj1++;
  std::cout << "ope= m_data_ = " << obj1.print() << std::endl;
  --obj1;
  std::cout << "ope= m_data_ = " << obj1.print() << std::endl;

  std::cout << "ope= m_data_ = " << obj1->print() << std::endl;
  return(0);
}


2項演算子のオーバーロード
2項演算子のオーバーロードは、演算子の右辺が引数として渡され、左辺のオブジェクトのオーバーロードした演算子が呼び出される。
例えば、data = obj1 + obj2;の時は、
data = obj1.+(obj2);
とこんな感じになる。

2項演算子のオーバーロードの例
#include 

class TEST
{
private:
  int m_data_;
public:
  TEST(int data) :m_data_(data)
  {
  };
  ~TEST(){};
  //データのセット
  void setData(int data)
  {
    m_data_ = data;
  }

  int print()
  {
    return(m_data_);
  }

  //2項演算子のオーバーロード
  int operator+(const TEST &obj)
  {
    return(m_data_ + obj.m_data_);
  }
  int operator-(const TEST &obj)
  {
    return(m_data_ - obj.m_data_);
  }
  int operator*(const TEST &obj)
  {
    return(m_data_ * obj.m_data_);
  }
  int operator/(const TEST &obj)
  {
    return(m_data_ / obj.m_data_);
  }
  int operator%(const TEST &obj)
  {
    return(m_data_ % obj.m_data_);
  }
  bool operator==(TEST &obj)
  {
    return(this->m_data_ == obj.m_data_);
  }
};

int main(int argc, char** argv)
{
  int data = 0;
  TEST obj1(2);
  TEST obj2(3);

  data = obj1 + obj2; 
  std::cout << "ope+ data = " << data << std::endl;

  data = obj1 - obj2; 
  std::cout << "ope- data = " << data << std::endl;

  data = obj1 * obj2;
  std::cout << "ope* data = " << data << std::endl;

  obj1.setData(10);
  obj2.setData(5);
  data = obj1 / obj2;
  std::cout << "ope/ data = " << data << std::endl;

  data = obj1 % obj2;
  std::cout << "ope% data = " << data << std::endl;

  if (obj1 == obj2)
  {
    std::cout << "m_data_の値は一緒です" << std::endl;
  }
  else
  {
    std::cout << "m_data_の値は等しくありません" << std::endl;
  }


  return(0);
}


添え字演算子のオーバーロード
添え字演算子をオーバーロードする事もできる。あるクラスを配列のように扱い、不正アクセスしないようにする事もできる。但し、オーバーヘッドがでかくなるので、お奨めではない。

添え字演算子の例
#include <iostream>
class TEST
{
private:
  int m_cur_data_;
  int *m_data_;
  unsigned int m_max_size_;
public:
  TEST(unsigned int size) : m_cur_data_(0), m_data_(0), m_max_size_(size)
  {
    if (m_max_size_ > 0)
    {
      m_data_ = new int[m_max_size_];
    }
  };
  TEST(const TEST& obj) : m_cur_data_(0), m_data_(0), m_max_size_(0)
  {
  }
  ~TEST()
  {
    if (m_data_ != NULL)
    {
      delete[] m_data_;
    }
  };
  void operator=(int data)
  {
    std::cout << "=" << std::endl;
    m_cur_data_ = data;
  }
  TEST& operator[](unsigned int suffix)
  {
    std::cout << "[]" << std::endl;
    if (suffix < 0 || suffix > m_max_size_)
    {
      std::cout << "不正メモリへのアクセスです" << std::endl;
    }
    else
    {
      std::cout << "要素[" << suffix << "]にデータ" << m_cur_data_ << "を格納しました" << std::endl;
      m_data_[suffix] = m_cur_data_;
    }
    return(*this);
  }
  int& operator[] (unsigned int suffix)
  {
    return (m_data_[suffix]);
  }
};

int main(int argc, char** argv)
{
  TEST obj(10);
  obj[1] = 3;
  return(0);
}


new・delete演算子のオーバーロード
new・delete演算子もオーバーロードできる。メモリ確保や開放のデバッグに有効
メンバ関数にする際は、静的メンバ関数にしなければならない。
グローバル関数にする際は、以下の書式となる。
void* operator new(size_t size){}
void* operator new[](size_t size){}
void operator delete(void* po){}
void operator delete[](void* po){}

new/delete演算子のオーバーロードの例
#include <iostream>
void* operator new(size_t size)
{
  std::cout << " alloc size = " << size << std::endl;
  return(malloc(size));
}

void* operator new[](size_t size)
{
  std::cout << " alloc size = " << size << std::endl;
  return(malloc(size));
}

void operator delete(void* po)
{
  std::cout << "delete address = " << std::hex << po << std::endl;
}

void operator delete[](void* po)
{
  std::cout << "delete address = " << std::hex << po << std::endl;
}

int main(int argc, char** argv)
{
  int *p_value1 = (int *)new int;
  int *p_value2 = (int *)new int[10];
  delete p_value1;
  delete[] p_value2;
}







Copyright 2007 ためになるホームページ All Rights Reserved.