C++ 再入門 その4 演算子の再定義
演算子というのは、計算式の中で登場する “+” であるとか “*” などの何らかの計算を行うような記号です。
演算子 - C++ プログラミング解説
加減乗除は小学生でも習う(掛け算が✕ではなく”*”だったり、割り算も÷じゃなくて”/”ですけど)ので馴染はあるとは思いますが、C言語やC++で使える演算子の数は他のプログラミング言語と比べてもかなり多く「え?これって演算子なの?」と悩んでしまうものもあります。
CとC++の演算子
多くはC言語と共通ですが中にはC++固有のものもあります。これらの演算子の間の優先順位も複雑で、加減算よりも乗除算が優先されるくらいはご存知かもしれませんが「比較演算子とビット演算子の優先度はどっちが上だっけ?」と慣れている人でも確認が必要になりがちなものもあります。もっとも嫌らしいのが「後置インクリメント」と「前置インクリメント」の関係あたりだったりしますけど。
さらにC++の特徴として、これらの演算子の働きをクラスの関数を書いて独自に拡張できるようになったのです。C言語であれば演算子は数値であったりポインタなどの値に対して働くだけですが、C++では値ではなくクラスに対して演算子を働かせることが出来るのです。
演算子オーバーロード
この機能を使ってC言語で関数を呼び出さないと書けなかった構造を持った値に対しても演算子を使って簡易に表現できるようになりました。文字列のクラスを用意すれば”+”を使って連結したり出来るわけです。この機能を使って標準ライブラリで拡張されている演算子もいくつかあります。例えば iostream で定義されている演算子の中に cout に使われていた “<<”もあります。
もともとの “<<”にはビットシフトの機能しかありませんが、いろいろな型であるとかクラスに対してこの演算子が定義されていて、型やクラスに対して入出力を行う関数を呼び出すことが出来るわけです。
iostream を使用した出力 - C++ ライブラリ・リファレンス
まずは、演算子を使って何らかの関数が呼ばれいろいろな処理が行われるとだけ理解していれば充分です。C++では言語仕様が複雑で、ある機能を理解するために、その都度、その機能の詳細まで踏み込んで把握する必要はありません。まず使ってみて、慣れたら応用して、その上で機能を使いこなすために詳細に進むのが常道です。もっとも見慣れないエラーメッセージを食らうと、結局いろいろ調べていく羽目にはなるのですけどね。
そもそも、ここまでの説明で顔を出している「オーバーロード」であるとか「多重定義」も何だかわからないですよね。それはそれで置いておいて、まずは演算子で使われる記号を書けば、どこかで定義されている関数が呼び出されて何らかの処理が行われるんだと理解して、それぞれのライブラリクラスの演算子を使えるようになれば充分です。
ということで、iostream に “<<” であるとか “>>” を使うことで、自動的に型やクラスに応じた文字列が入出力されるんだよと理解してください。自動では充分ではなければ「マニピュレータ」と呼ばれる関数を書くことで「出力幅」「位置合わせ」「精度」や「基数」を指定することが出来ます。
iostream プログラミング
挿入演算子と制御形式の使用
ここまででC言語でprintfの最初の引き数で書いていた書式指定文字列を置き換えてみることを目指してください。慣れてしまえば書式と変数の対応でわかりにくくなっていた場合に少しは楽になったことに気づくとは思います。もっとも複雑な書式が欲しいときには一気に処理することが出来ずにやぶ蛇だよなと思うこともありますが。そういう時には、個別に複雑な処理を書くのではなく、その処理を包括するクラスを書いて、そちらに任せるのがC++です。そして作ったクラスに iostream に対する処理を書くのです。
文字や数値を入出力するだけで、何だか「おおごと」に感じるかもしれませんが、やるべき事が分かりやすい機能からC++で扱えるようになったオブジェクトであるとかクラスという考え方に入っていくのが第一歩です。
さてもっと詳しく知りたい人のために、いくつかのページを紹介しておきます。
独自クラスをストリーム出力に対応させる - C++ プログラミング
C++ の組み込み演算子、優先順位、結合規則
演算子のオーバーロード
ヘッダ画像は、以下のものを使わせていただきました。
https://commons.wikimedia.org/wiki/File:ISO_C%2B%2B_Logo.svg
Jeremy Kratz - https://github.com/isocpp/logos, パブリック・ドメイン, https://commons.wikimedia.org/w/index.php?curid=62851110による