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

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

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

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

Q&A

解決済

3回答

583閲覧

c++のクラスオーバーロードの挙動について質問です。

kinoko-_.

総合スコア8

C++

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

0グッド

0クリップ

投稿2022/01/08 06:25

編集2022/01/08 08:51

#include<iostream>

stringクラスを定義し、stringオブジェクトをmain関数にてそれぞれs,w,eを作成。
sとwにはそれぞれpとqに値を入れ、それらを演算子のオーバロードで足し合わせて、eのオブジェクトに格納しようとしてます。

ここで疑問なのですが、なぜこのようなコードにすると結果が(500,0)と返ってくるのでしょうか?
return文の際にreturn string(p + stm.p, q + stm.q)と書くとなぜしっかりpとqの足した値が返ってくるのでしょうか?
return文の際、stringの型で返さなければsの(p,q)だけ計算される仕組みがよくわかりません。

※sの(p,q)とはsのオブジェクトの値であるs(200, 300)を指します。
本来ならreturn string(p + stm.p, q + stm.q)すると
sの200の値とwの100の値が足し合わさってeのpには300が格納され
eのqにはsのqとwのqが足し合わさってeのqには500が格納されるコードです。
ただreturn文で
return string(p + stm.p, q + stm.q)
上記のような記述をするとしっかり計算してくれるのですが
return (p + stm.p, q + stm.q)
上記のような書き方をすると値が(500,0)と表示されてしまいます。
このように帰ってくるのはなぜなのか
このあたりの挙動がよくわかりません。

struct string
{
int p;
int q;

string(int x = 0, int y = 0) { this->p = x; this->q = y; } string operator+(string& stm) { return (p + stm.p, q + stm.q); }

};

int main() {
string s(200, 300);
string w(100, 200);
string e;

e = s + w; std::cout << e.p << std::endl << e.q; return 0;

}

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

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

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

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

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

maisumakun

2022/01/08 06:33

> return文の際、stringの型で返さなければsの(p,q)だけ計算される どういう意味でしょうか?
BeatStar

2022/01/08 06:49

クラスではなく構造体では? struct Stringとなっているし。
guest

回答3

0

ここで疑問なのですが、なぜこのようなコードにすると結果が(500,0)と返ってくるのでしょうか?

「それがルールだから」では納得できませんかね。

return (p + stm.p, q + stm.q);
式を , で繋ぐと左から順に評価され、(~) 全体としては最終式の評価値となります。まずそれがルール。

なので (300, 500) は 500と評価されるのですが、
関数(ここでは operator+)はstringを返すと定義したのですから、
コンパイラは500をstringに変換しようと試みます。

その結果stringのコンストラクタ:string(int x=0, int y=0)とマッチするので string(500)、
すなわちデフォルト引数で y=0 が補われて string(500,0) が返ります。

return文の際にreturn string(p + stm.p, q + stm.q)と書くとなぜしっかりpとqの足した値が返ってくるのでしょうか?

stringのコンストラクタを明示的に呼び出すからです。

※ 両者は () の意味が違う。
前者は評価の優先度を強制する(数式で出てくるフツーの)カッコ
後者は関数(ここではコンストラクタ)の引数を指定するカッコ

[追記] いまどきのC++なら

C++

1 string operator+(string& stm) { 2 return {p + stm.p, q + stm.q}; 3 }

と書くとアラ不思議...

投稿2022/01/08 06:43

編集2022/01/08 08:09
episteme

総合スコア16614

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

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

kinoko-_.

2022/01/08 09:16

納得しました。 戻り値を書かないと関数のカッコではなくなり、評価の優先度が現れる()になるんですね。 非常に勉強になりました。ご回答ありがとうございました。
guest

0

C++

1return (p + stm.p, q + stm.q);

この部分はカンマ演算子として解釈され、最後の式(q+stm.q)が値となり、この値がstringのコンストラクタに渡されます。

C++

1string(500, 0) // 500->q+stm.q, 0->デフォルト値

return のところでコンストラクタを呼び出ししたいなら下記のように記載します。

C++

1return string(p + stm.p, q + stm.q); //明示的にコンストラクタを呼ぶ 2return {p + stm.p, q + stm.q}; // 初期化子リストで渡す

投稿2022/01/08 06:49

Serbonis

総合スコア581

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

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

episteme

2022/01/08 08:16

> return {p + stm.p, q + stm.q}; // 初期化子リストで渡す どうなんだろ、これは初期化子リストなのかな? 一様初期化(uniform initializaton)ではないかしら。
Serbonis

2022/01/08 12:04

それです、用語間違えました
guest

0

ベストアンサー

cpp

1return (p + stm.p, q + stm.q);

このときの , はカンマ演算子です。 カンマ演算子は左辺を無視して右辺の値を返すという効果があります。

また、 return 文に与えられた式 (の結果) と返却値の型が異なる場合には暗黙の型変換が適用されます。 そして暗黙の型変換には変換コンストラクタが使われます。

デフォルト引数や可変長引数も含めて引数ひとつを受け取ることが可能なコンストラクタは変換コンストラクタです。 故に string(int x = 0, int y = 0) は変換コンストラクタとして機能します。

以上をふまえて質問のコードで暗黙に処理される内容を明示的に書くとするとこうなっているのと同じことです。

cpp

1#include <iostream> 2 3struct string 4{ 5 int p; 6 int q; 7 8 string(int x = 0, int y = 0) { 9 this->p = x; 10 this->q = y; 11 } 12 13 string operator+(string& stm) { 14 p + stm.p; 15 return string(q + stm.q); 16 } 17}; 18 19int main() { 20 string s(200, 300); 21 string w(100, 200); 22 string e; 23 24 e = s + w; 25 std::cout << e.p << std::endl << e.q; 26 27 return 0; 28}

投稿2022/01/08 06:43

SaitoAtsushi

総合スコア5437

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

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

episteme

2022/01/08 08:22

> カンマ演算子は左辺を無視して右辺の値を返すという効果があります。 ちょっと誤解を生みそうなのでコメント 「左辺(は評価はするがその値)を無視して」ですよね。 # じゃないと f(), g() は 「f()は呼ばれない」ことになってしまう。
kinoko-_.

2022/01/08 09:09

return文と戻り値の型が違うと変換コンストラクタが自動で働くんですね。 非常に勉強になりました。ご回答ありがとうございました。
SaitoAtsushi

2022/01/08 09:19

実引数と仮引数、そして代入などにおいても暗黙の型変換は働きます。 暗黙の型変換の一種として変換コンストラクタが働く場合もあるのであって、変換コンストラクタ以外の形で型変換が起こることもあります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問