C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++における単項演算子のオーバーロード方法を徹底解説

C++では、operatorキーワードを使って関数を宣言することで、クラスのインスタンスに適用した際の演算子の意味を独自に定義できます。これにより、1つの演算子に複数の意味を持たせることができ、これを「オーバーロード」と呼びます。コンパイラは、オペランドの型を調べることで、どの定義を適用すべきかを判断します。

単項演算子とは

単項演算子は、1つのオペランドに対してのみ作用する演算子です。代表的な単項演算子には以下のようなものがあります。

  • インクリメント(++)およびデクリメント(--)演算子
  • 単項マイナス(-)演算子
  • 論理NOT(!)演算子

単項演算子は、それが呼び出されたオブジェクトそのものに対して動作します。通常は !obj-obj++obj のようにオブジェクトの左側(前置形式)に記述しますが、obj++obj-- のように後置形式(ポストフィックス)で使われる場合もあります。

「!」演算子をオーバーロードするサンプルコード

以下の例では、論理NOT(!)演算子を前置形式でオーバーロードし、距離クラスの各メンバ変数の符号を反転させる方法を示しています。

#include <iostream>
using namespace std;

class Distance {
   private:
   int feet; // 0 to infinite
   int inches; // 0 to 12

   public:
   // コンストラクタ
   Distance(int f, int i) {
      feet = f;
      inches = i;
   }

   // 距離を表示するメソッド
   void display() {
      cout << "F: " << feet << " I:" << inches <<endl;
   }

   // 「!」演算子のオーバーロード
   Distance operator!() {
      feet = -feet;
      inches = -inches;
      return Distance(feet, inches);
   }
};
int main() {
   Distance D1(3, 4), D2(-1, 10);

   !D1;
   D1.display();   // D1を表示

   !D2;            // 符号を反転
   D2.display();   // D2を表示

   return 0;
}

実行結果

このプログラムを実行すると、以下の出力が得られます。

F: -3 I:-4
F: 1 I:-10

ポイントまとめ

operator! のようにメンバ関数として単項演算子をオーバーロードする場合、引数は不要です。これは、演算対象となるオブジェクト自身(thisポインタが指すオブジェクト)が暗黙的に渡されるためです。上記の例では、! 演算子が適用されるたびに feetinches の符号が反転され、反転後の値を持つ新しい Distance オブジェクトが返されます。

  1. C++の単項演算子とは?種類と使い方を徹底解説

    単項演算子とは単項演算子とは、たった1つのオペランドに対して作用し、新しい値を生成する演算子のことです。C++にはさまざまな単項演算子が用意されており、それぞれ異なる役割を持っています。本記事では、代表的な単項演算子の種類とその動作について詳しく解説します。C++の主な単項演算子一覧間接参照演算子(*) - ポインタ変数に対して作用し、ポインタが指すアドレス上の値と等価なl値を返します。この操作は「デリファレンス(参照外し)」とも呼ばれます。アドレス演算子(&) - オペランドのアドレスを取得します。オペランドには、関数指定子、またはビットフィールドではなくregister記憶クラス指

  2. C++の単項演算子とは?種類・使い方を実例付きで解説

    単項演算子(unary operator)とは、1つのオペランド(被演算子)に対して作用し、新しい値を生成する演算子のことです。C++には以下のような単項演算子が用意されています。 C++の主な単項演算子一覧 演算子説明 間接参照演算子(*)ポインタ変数に作用し、そのポインタが指すアドレスにある値に相当するlvalueを返します。この操作はポインタの「デリファレンス(間接参照)」と呼ばれます。 アドレス取得演算子(&)オペランドのメモリアドレスを取得する単項演算子です。オペランドとしては、関数指定子、またはビットフィールドでなく、register記憶クラス指定子を付けずに宣言さ