質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

5回答

1621閲覧

C++の型宣言でoperatorを使う

seri

総合スコア422

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/01/09 11:11

とあるサイトで以下のようなコードを見ました
(ofFbo ,FBOs[]はOpenFrameworks組み込みの関数ですので気にしないでください)

ofFbo& operator[]( int n ){ return FBOs[n];}

このような
型名 & operator[]
とゆう記述をしたことがなく、どういった実装になるのか調べたいのですが、検索しようにも& Operatorだけでは別の項目ばかりでてきてしまいます、
このような実装法に名前などありましたら教えてください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

二つの機能の複合ですので、それぞれ解説します。

###参照を返す関数 型& 関数名(引数) {コード}

C++には参照という機能があります。変数を参照として扱ったり、関数の引数として参照を渡したりなどが可能です。値を渡すよりも、コピーが発生しない分だけ高速になり、また、参照元そのものを変更できます。

C++

1#include <iostream> 2using namespace std; 3void tiwce(int &x) 4{ 5 x *= 2; 6} 7int main(void) 8{ 9 int a = 0; 10 int &b = a; 11 b = 1; 12 cout << a << endl; // => 1 13 tiwce(a); 14 cout << a << endl; // => 2 15}

baの参照です。ですので、bへの代入もaへの代入と同じになります。また、関数twice内でのxtwice(a)の呼び出しでは、aへの参照になります。つまり、xに代入したら、同じようにaへの代入になります。ここまでは普通の参照の使い方です。int型などではあまり意味がありませんが、このように参照を使うと、大きなクラスや構造体の場合、コピーが発生しないため、処理が高速になります。また、関数内で引数の変数そのものを変更すると言ったことも可能になります。

ここまではいいですね。これだけではなく、C++は参照を返す事もできます。それが型& 関数名(引数) {コード}という書き方です。

#include <iostream> using namespace std; int &add(const int x) { static int r = 0; r += x; return r; } int main(void){ int &a = add(1); cout << a << endl; // => 1 add(2); cout << a << endl; // => 3 a = 5; int b = add(1); cout << b << endl; // => 6 }

rは関数内のstaticなローカル変数です。関数addrへの参照を返し、arへの参照になります。ですので、二回目のadd(2)で関数内のrが変われば、aの内容も変わります。また、逆にaに代入すればrも変わります。なお、brの参照ではなく、代入によってrの値がコピーされまることがaとは異なります。bを変更してもrは変わりません。

※ 参照を返す場合、自動変数を返してはいけません。関数が終わっても存続しているstaticなローカル変数やレシーバーそのものやメンバー変数等を返す必要があります。

参照を返すメリットは、同様に速度です。クラスや構造体であれば、値のコピーが発生し、処理にコストがかかります。

※ C++11以降はムーブセマンティクスによって、参照を返すのと同じようにコピーを発生させずに値を返す方法があります。

###演算子をオーバーロードする関数 型 operator記号(引数) {コード}

+[]などは演算子と言われますが、C++ではこの演算子の動作を定義することができます。これを演算子オーバーロードといいます。ただ関数名として記号はそのまま使用できません。operator記号という特殊な関数名を使います。+であればoperator+[]であればoperator[]という形です。

#include <iostream> using namespace std; class NeoInt { int i = 0; public: NeoInt(int i) : i(i) {} int operator[](int x) { return i + x; } }; int main(void){ NeoInt ni(1); int a = ni[2]; cout << a << endl; // => 3 }

ni[2]は何か特殊なことをしているように見えますが、実質は関数operator[]を呼び出しているに過ぎません。このように、演算子についても独自で定義することで、独自のクラスであっても他の数値型と同じように扱ったり、cout << xのような形で出力したりすることが可能です。

なお、+のような一部の二項演算子については、メンバー関数として定義する方法以外に非メンバー関数として定義する方法もあります。a + bと言う形の場合、a.operator+(b)operator+(a, b)のいずれかを見に行く事になります。

投稿2017/01/09 12:25

編集2017/01/09 12:26
raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

例えば、以下のようなクラスがあった場合・・・

c++

1class sample{ 2 const char *ptr; 3public: 4 sample(const char *p):ptr(p){} 5 char operator[](int n)const{ return *(ptr+n);} 6} 7 8sample a("abcdefg");

a[1]は、2つ目に格納されてい文字('b')を返します。

投稿2017/01/09 12:01

編集2017/01/09 12:05
cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

該当関数の定義は、下記のように区切って読み下してください。

C++

1 ofFbo& operator[]( int n ){...} 2// ~~~~~~ 戻り値の型 3// ~~~~~~~~~~ 関数名 4// ~~~~~~~~~ 関数の引数リスト

関数名が operator■ のときは、演算子に対する「演算子オーバーロード(operator overload)」となります。ここでは添え字演算子[]のオーバーロードです。

C++言語ではoperatorはキーワード(予約語)ですから、このキーワードが含まれる場合は演算子オーバーロード関連だと解釈すれば大丈夫です。(厳密には違いますは当座は困らないでしょう)

投稿2017/01/09 11:54

編集2017/01/09 11:58
yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こんにちは。

それは演算子オーバーロードです。

投稿2017/01/09 11:42

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

「c++ 連想配列」で検索してみてください。

投稿2017/01/09 11:40

naomi3

総合スコア1105

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問