[] と () 演算子のオーバーロード
CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 45/104。
添字演算子 ([]) を使用すると、クラスを配列のように動作させることができ、要素へのインデックスによるアクセスが可能になります。関数呼び出し演算子 (()) は、オブジェクトを呼び出し可能なエンティティ(ファンクタとして知られています)に変えます。
添字演算子を使用した単純な配列ラッパーを以下に示します:
class IntArray {
int* data;
size_t size;
public:
IntArray(size_t s) : size(s), data(new int[s]()) {}
~IntArray() { delete[] data; }
int& operator[](size_t index) {
return data[index];
}
const int& operator[](size_t index) const {
return data[index];
}
};2つのバージョンを提供していることに注目してください。1つは非const参照を返し(変更が可能)、もう1つのconstバージョンはconstオブジェクトで動作します。これにより、読み取りと書き込みの両方でarr[0] = 5;と記述できるようになります。
関数呼び出し演算子は、関数のように「呼び出す」ことができるオブジェクトを作成します。
class Multiplier {
int factor;
public:
Multiplier(int f) : factor(f) {}
int operator()(int value) const {
return value * factor;
}
};
Multiplier triple(3);
int result = triple(10); // 30を返しますファンクタは、通常の関数とは異なり、呼び出し間で状態を維持できるため強力です。これらは、設定値を保持するカスタマイズ可能な動作が必要なSTLアルゴリズムで一般的によく使用されます。
チャレンジ
簡単添字演算子と関数呼び出し演算子の両方を組み合わせた ScoreTracker クラスを作成しましょう。このクラスはプレイヤーのスコアを保存し、[] を使用してインデックスでアクセスできるようにすると同時に、渡されたスコアにボーナス倍率を適用するファンクタとしても機能します。
コードを整理するために、2つのファイルを作成します。
ScoreTracker.h: プレイヤースコアの配列を管理し、ボーナスを適用できるScoreTrackerクラスを定義します。クラスには以下のものを含める必要があります。- スコアを保存するための動的に割り当てられた
int*配列 - スコアの数を保持する
size_tメンバ - ボーナス倍率を保持する
doubleメンバ - サイズとボーナス倍率を受け取り、すべてのスコアを 0 に初期化するコンストラクタ
- 動的メモリを適切にクリーンアップするデストラクタ
- インデックスでスコアにアクセスするための 添字演算子
[](const 版と非 const 版の両方) intのスコアを受け取り、そのスコアにボーナス倍率を掛けた値を (intとして) 返す 関数呼び出し演算子()- スコアの数を返す
getSize()メソッド
非 const の添字演算子は、
tracker[0] = 100;のように書き込めるように参照を返します。const 版は、const オブジェクトに対して読み取り専用のアクセスを許可します。関数呼び出し演算子は、オブジェクトの状態を変更しないため、constとしてマークする必要があります。- スコアを保存するための動的に割り当てられた
main.cpp: 以下の入力を読み取ります (それぞれ別の行にあります)。- プレイヤー数 (サイズ)
- ボーナス倍率 (double 型)
- 各プレイヤーのスコア (1行に1つ、サイズ分)
- ボーナスを適用するテストスコア
ScoreTrackerを作成し、添字演算子を使用して各プレイヤーのスコアを保存してから、すべてのスコアを表示します。最後に、関数呼び出し演算子を使用して、ボーナスが適用されたスコアを計算します。出力形式:
Player 0: <score> Player 1: <score> ... Bonus applied to <test_score>: <result>
例えば、プレイヤーが3人、倍率が 1.5、スコアが 100, 200, 150、テストスコアが 80 の場合:
Player 0: 100
Player 1: 200
Player 2: 150
Bonus applied to 80: 120入力の変換には std::stoi() と std::stod() を使用してください。ヘッダーファイルにはインクルードガードを忘れないでください。
チートシート
添字演算子 [] を使用すると、オブジェクトに配列のようにアクセスできるようになります。関数呼び出し演算子 () は、オブジェクトを関数のように呼び出し可能(ファンクタ)にします。
添字演算子
読み取り/書き込みアクセスのために、const版と非const版の両方を提供します:
class IntArray {
int* data;
size_t size;
public:
IntArray(size_t s) : size(s), data(new int[s]()) {}
~IntArray() { delete[] data; }
// Non-const version: allows modification
int& operator[](size_t index) {
return data[index];
}
// Const version: read-only access
const int& operator[](size_t index) const {
return data[index];
}
};関数呼び出し演算子
呼び出し間で状態を保持できるファンクタを作成します:
class Multiplier {
int factor;
public:
Multiplier(int f) : factor(f) {}
int operator()(int value) const {
return value * factor;
}
};
Multiplier triple(3);
int result = triple(10); // Returns 30ファンクタは、保存された設定によるカスタマイズ可能な動作が必要なSTLアルゴリズムで役立ちます。
自分で試してみよう
#include <iostream>
#include <string>
#include "ScoreTracker.h"
using namespace std;
// TODO: ScoreTracker のコンストラクタを実装する
ScoreTracker::ScoreTracker(size_t size, double multiplier) {
// TODO: メンバを初期化し、動的配列を割り当てる
// すべてのスコアを 0 に初期化する
}
// TODO: ScoreTracker のデストラクタを実装する
ScoreTracker::~ScoreTracker() {
// TODO: 動的メモリをクリーンアップする
}
// TODO: 非 const 添字演算子を実装する
// TODO: const 添字演算子を実装する
// TODO: 関数呼び出し演算子を実装する
// TODO: getSize メソッドを実装する
size_t ScoreTracker::getSize() const {
// TODO: スコアの数を返す
}
int main() {
string line;
// プレイヤーの数を読み込む
getline(cin, line);
size_t numPlayers = stoi(line);
// ボーナス倍率を読み込む
getline(cin, line);
double multiplier = stod(line);
// TODO: numPlayers と multiplier を使用して ScoreTracker を作成する
// TODO: 各プレイヤーのスコアを読み込み、添字演算子を使用して格納する
// TODO: テストスコアを読み込む
// TODO: すべてのプレイヤースコアを "Player X: <score>" の形式で表示する
// TODO: ボーナス適用結果を "Bonus applied to <test_score>: <result>" の形式で表示する
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
3コンストラクタとデストラクタ
デフォルトコンストラクタ引数付きコンストラクタコピーコンストラクタムーブコンストラクタコンストラクタ初期化リスト委譲コンストラクタデストラクタ詳解Rule of Three / Five / Zeroまとめ - Stringクラス6演算子オーバーロード
演算子オーバーロード入門算術演算子のオーバーロード比較演算子のオーバーロードストリーム演算子代入演算子のオーバーロード[] と () 演算子のオーバーロード型変換演算子まとめ:Matrix クラス