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

C++におけるストリーム挿入(<<)・抽出(>>)演算子のオーバーロード入門

C++では、ストリーム挿入演算子 << とストリーム抽出演算子 >> を使うことで、int や double などの組み込みデータ型の入出力を簡単に行えます。実は、これらの演算子はユーザー定義型(クラスのオブジェクトなど)に対してもオーバーロードでき、独自クラスでも標準型と同じように cincout を使った入出力が可能になります。

なぜfriend関数として宣言するのか

ここで重要なポイントがあります。演算子オーバーロード関数は、クラスのfriend(フレンド)関数として宣言する必要があるという点です。

その理由は、cout << D1; のように使う場合、左辺がストリームオブジェクトであり、クラスのオブジェクトではないためです。つまり、この演算子関数はクラスのメンバ関数として呼び出されるのではなく、オブジェクトを生成せずに外部から呼び出される形になります。friend宣言を行うことで、privateメンバへのアクセス権を持ちながら、クラス外に定義された関数として機能させることができます。

サンプルコード

以下の例では、距離を表す Distance クラスに対して、抽出演算子 >> と挿入演算子 << をオーバーロードする方法を示しています。

#include <iostream>
using namespace std;

class Distance {
private:
    int feet;    // フィート(0以上)
    int inches;  // インチ(0〜12)
public:
    // 必要なコンストラクタ
    Distance() {
        feet = 0;
        inches = 0;
    }
    Distance(int f, int i) {
        feet = f;
        inches = i;
    }
    // 挿入演算子<<のオーバーロード
    friend ostream &operator<<( ostream &output, const Distance &D ) {
        output << "F : " << D.feet << " I : " << D.inches;
        return output;
    }
    // 抽出演算子>>のオーバーロード
    friend istream &operator>>( istream &input, Distance &D ) {
        input >> D.feet >> D.inches;
        return input;
    }
};

int main() {
    Distance D1(11, 10), D2(5, 11), D3;
    cout << "Enter the value of object : " << endl;
    cin >> D3;
    cout << "First Distance : " << D1 << endl;
    cout << "Second Distance :" << D2 << endl;
    cout << "Third Distance :" << D3 << endl;
    return 0;
}

実行結果

$./a.out
Enter the value of object :
70
10
First Distance : F : 11 I : 10
Second Distance :F : 5 I : 11
Third Distance :F : 70 I : 10

コードの解説

このプログラムのポイントを整理すると、次のとおりです。

  • 挿入演算子(<<)のオーバーロード: 第1引数に ostream&、第2引数に出力したいオブジェクトへの参照を受け取ります。処理後はストリームへの参照を返すことで、cout << A << B; のような連続的な出力(チェーン呼び出し)に対応できます。
  • 抽出演算子(>>)のオーバーロード: 第1引数に istream&、第2引数に値を読み込むオブジェクトへの参照を受け取ります。こちらもストリームを返すことで連続入力が可能になります。
  • friend宣言: 両方の演算子関数はクラス内でfriendとして宣言されているため、privateメンバである feetinches に直接アクセスできます。
  • const参照: 出力用の operator<< では、対象オブジェクトが変更されないよう const Distance& を受け取っています。これは安全な設計の定石です。

このようにストリーム演算子をオーバーロードしておけば、自作クラスのオブジェクトも cin >> obj;cout << obj; という直感的な構文で入出力できるようになり、コードの可読性と再利用性が大きく向上します。

  1. C++のインクリメント(++)とデクリメント(--)演算子の基礎と使い方

    インクリメント演算子とデクリメント演算子とはC++には、値を1だけ増減させるための便利な演算子が用意されています。インクリメント演算子「++」はオペランド(対象の値)に1を加え、デクリメント演算子「--」はオペランドから1を引きます。つまり、以下の2つのコードは同じ意味になります。x = x + 1; は x++; と同じ同様に、次の2つも同じ意味です。x = x - 1; は x--; と同じ前置き(prefix)と後置き(postfix)の違いインクリメント・デクリメント演算子には、オペランドの前に置く「前置き(prefix)」と、後ろに置く「後置き(postfix)」の2つの書き方があり

  2. C++における演算子オーバーロードの基本ルールとイディオムとは?

    C++における演算子オーバーロードの3つの基本ルール C++で演算子をオーバーロードする際には、守るべき3つの基本ルールがあります。あらゆるルールに例外が存在するように、これらにも例外はありますが、まずは以下の原則を押さえておきましょう。 ルール1:意味が明確でない演算子はオーバーロードしない 演算子の意味が明白で、誰もが異論なく受け入れられる場合以外は、オーバーロードすべきではありません。その代わりに、適切な名前を持つ関数を提供しましょう。この最初にして最も重要なルールの核心は、一言でいえば次の通りです。 「やめておけ」 これは意外に聞こえるかもしれませんが、演算子オーバーロードが適切なケ