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

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

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

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

Q&A

解決済

3回答

4035閲覧

if文の条件式で代入してますが仕組みがわかりません。

gemfighter

総合スコア38

C++

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

0グッド

0クリップ

投稿2020/11/16 08:39

編集2020/11/16 09:39

C++

1コード 2 3//基底クラス 4class Bottom 5{ 6 public: 7 char esc; 8 char kind; 9 short x1; 10 short y1; 11 short x2; 12 short y2; 13 long foreColor; 14 long backColor; 15}; 16 17//派生クラス 18class StraightLine : public Bottom 19{ 20 public: 21 22 char lineKind; 23 char NOT_USE; 24 short startX; 25 short startY; 26 short endX; 27 short endY; 28 29 //コンストラクタ 30 StraightLine(); 31 32 //デストラクタ 33 ~StraightLine(); 34 35}; 36 37 38int main() 39{ 40 StraightLine *straightine = new StraightLine[2]; 41 std::vector<Bottom> bases;//全部入れるテーブル 42 43 //ここらへんでpush_backでvectorにデータを入れています。 44 45//イテレータで回しています 46for (vector<Bottom>::iterator it = begin(bases); it != end(bases); ++it) 47 { 48 49 50         //聞きたいところはここです 51 if (straightine = dynamic_cast<StraightLine*>(it)) { 52 53 //ここで派生クラスの関数で出力している 54 55 } 56 57 } 58} 59 60 61 62```現在、会社の研修であるプログラムを作っていますが、レビューで仕組みを説明できなくて困っています。 63それが、基底クラスのvectorに派生クラスのデータを入れ、後でiteratorのfor文で回しながらvectorの中に入ってるデータを出力するところなのですが、iteratorからvectorの中の派生クラスのデータを出力しようとしたら、iteratorから派生クラスの中のデータにアクセス出来ないのです。 64 65そのため、if文で条件式の中で新たに作った派生クラスのインスタンスの中にvectorのデータを代入して代入できたら出力するといった処理を書きました。 66 67ですが、説明しても違うと言われ、資料を探しても関連したものが見つからなくて困っています。 68 69うまい説明ができる方は教えてくださいますようお願いします。

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

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

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

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

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

y_waiwai

2020/11/16 08:40

そのコードを提示しましょう
Zuishin

2020/11/16 08:47

この説明はうまくできているんでしょうか?
fana

2020/11/16 09:12

「違う」と言っている人に詳細を尋ねない理由は何か? 何故他所で訊くのか? (質問文面だけ見るとスライシングしてそうだが)
fana

2020/11/16 09:18

それはそれとして, ifによって代入の可否を判断するという話がどのような実装となるのかがピンと来ないので 後学のためにコード提示いただきたいところ.
gemfighter

2020/11/16 09:39

詳細を訪ねようとしても課題にならないからと言って教えてくれませんでした。
Zuishin

2020/11/16 09:40

ここで尋ねても課題にならないのでは?
gemfighter

2020/11/16 09:41

どこを調べても答えにたどり着けないので、もう他の人に聞きたくてここに書きました。
Zuishin

2020/11/16 09:43

そういう時は指導者に「わかりませんでした」と正直に言うのが成功の一番の近道です。できたふりをすると取りこぼされます。
gemfighter

2020/11/16 09:44

解らないといっても最後まで頑張れと言われたので困っています。
fana

2020/11/16 09:48

このコードでまともな(所望の,あるべき)表示が成されるのか否かを動作確認されたのでしょうか? した場合→その結果はどうでした?
gemfighter

2020/11/16 09:51

ちゃんと動作しています。 ただ、条件式で代入できているかできてないかで判断しているとしか理解できていないため、説明ができないのです。
fana

2020/11/16 10:19 編集

仮にそのdynamic_castがコンパイル通るのだとしても,所望の結果を返すようには思えないです. 逆に言えば,「これでまともに動くのであって,その仕組みを説明するのだ」という話であるならば, 個々の要素に関して具体的な説明をしていけば良いのではないでしょうか. ・「基底クラスのvectorに派生クラスのデータを入れ」たらどうなるのか ・「iteratorから派生クラスの中のデータにアクセス出来ない」のは何故か ・その対処として記述したifの箇所の処理に関して  ・std::vector<Bottom>::iterator を dynamic_cast<StraightLine*> するとどうなるのか  ・そのdynamic_cast結果を代入する式の評価結果で分岐するifの具体的意味は何か  ・その他,StraightLine *straightine = new StraightLine[2]; ← これの[2]の理由とか … といった具合に.一つ一つ.
gemfighter

2020/11/16 10:21

そうじゃなく、if文の仕様を説明しろみたいなことを言われました。
fana

2020/11/16 10:26

であれば,説明すればよいのでは…… 例えば,ifに関してちょっとふわっとしている場合でも, if( a == 1 ) //aが1だったら みたいなコードを書くことはできると思うのですが, if( a = func() ) //()内が比較じゃないぞ? といったコードを書くには相応の理解があるであろうと見えるので,訊かれているのだと思います.
gemfighter

2020/11/16 10:31

代入できるかできないかで判断して真理値を返しているみたいな説明しても違うといわれて困っているのです。 もう、どう説明した良いのか解らないのです。
fana

2020/11/16 10:37 編集

何だろう,もっと根本的に if( X ){ 処理A; } とか書いた時,「XがどうだったらAが実施されるのか」というのを"ifの仕様"と呼ぶのではないでしょうか. まずはそこのところからの説明が要求されているのでは?
gemfighter

2020/11/16 10:40

そうじゃないらしいですね。 まず、「if文の条件文は比較演算子を書くのに、何で代入演算子で動作返しているかを答えなさい」みたいなことを言われました。 なのでどう説明したらいいのか解らないのです。
Zuishin

2020/11/16 10:46

そこがわからないと書けないコードですが、あなたはこれを自分で書いたと言って提出したんですか?
gemfighter

2020/11/16 10:48

代入出来たら結果を返すという漠然とした仕組みは知っていたので書けました。 ただ、レビューでどうやって説明したらいいか解らないんです。
fana

2020/11/16 10:49

いや,だから, (1) 代入文というのは,これこれこういう形に評価されるのであって, (2) 他方,ifの仕様というのは「Xの部分がこうだったらこうなる」というものであるからして, (3) よって,(1)と(2)より,代入文をif( X ) のXの部分に書いた場合には… とか説明していけば良いのではないのか? そこに代入文を書いたのは他ならぬあなたなのだから,当然 (1)~(3) は理解しているハズ(不足/不安ならCの基礎みたいなのをググるなりして2時間くらい復習でもすればいいし)で,あとはそれを順序立ててうまいこと「if文の条件文は比較演算子を書くのに」とかほざいている野郎を論破すれば良いのではないのか?
Zuishin

2020/11/16 10:49

いいえ、それだけでは書けません。どう説明したらいいかわからないのではなく、あなた自身がこのコードの意味がわかっていません。 わからないまま人に聞いたりコピペしたりして泥沼にはまっているようにしか見えませんが、このままずぶずぶ行くつもりでしょうか?
fana

2020/11/16 10:59

説明の形の1つとして… int Func1(){ return 1; } int Func2(){ return 2; } ... if( Func1() + Func2() ){ A; } とかいうのがある時,これを要約(変形?)していけば if( Func1() + Func2() ){ A; } というのは if( 1 + 2 ){ A; } になって,それは最終的に if( 3 ){ A; } //←ここまできたら「ifの仕様:処理Aを実施するかしないか」という話になる になるよね,みたいな. これと同じように,あなたが書いたifを要約していけばどうでしょう? (dynamic_castがit次第で何返すか異なるけども,そのパターン分の要約を示せばいい)
kazuma-s

2020/11/16 11:12

コンパイルすらできないコードで質問しても意味がありません。 dyanmic_cast<型>(式) は、型も式も、ポインタか参照でないといけません。 if (straightine = dynamic_cast<StraightLine*>(it)) { の it はクラスのインスタンスであって、 ポインタではありません。
fana

2020/11/16 11:13

(とりあえずここまでの複数個のコメントによって,今からでも把握すればよさそうな事柄に関しては割と網羅できたのではないかと思うけど…どうかな?)
gemfighter

2020/11/16 12:37

>>kazuma-sさん すみません、会社で書いたコードを思い出しながら書いたので、少し間違っているかもしれません。 ですが、今回はif文の条件文で何故代入演算子で動くかについての説明ですので、その説明をおねがいしたいのです。 >>fanaさん if文に代入演算子を使うと、代入され、普通なら条件は常に条件は常に真理値が真の状態になります。 ただ今回はベクタに入っているデータを派生クラスのインスタンスに代入する式になっているので、代入できるかどうかの判定の式になります。 だいたいこんな説明をしました。
raccy

2020/11/16 13:28

> すみません、会社で書いたコードを思い出しながら書いたので、少し間違っているかもしれません。 https://wandbox.org/permlink/xMxhkn6xBGJo7QOF 今のコードはコンパイルエラーになるだけなので、説明する以前の状態です。せめてちゃんとコンパイルして動作するコードにしてからでないと、回答の前提となっている質問のコードが間違っている可能性が高く、回答が無駄になってしまいます。プログラムは一文字違っただけで全く違う動作や逆の動作をする時もあります。「少しの間違い」は「大きな間違い」です。 コードの説明を求めるなら、まともに動くプログラムで質問するようにお願いします。
guest

回答3

0

自己解決

すみません、どうやら条件式の中で値が0かそれ以外で判別してるという答えが欲しかったみたいです。
ご迷惑おかけしました。

投稿2020/11/24 08:21

gemfighter

総合スコア38

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

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

0

至極単純な例ですが

#include <iostream> int main() { int a = 100, b = 0; if (a = b) std::cout << "true" << std::endl; else std::cout << "false" << std::endl; std::cout << a << std::endl; return 0; }

この結果はどうなるでしょうか。aの値からみて代入は成功? 失敗?

参考としてC++とCの言語規格を挙げておきます。

JIS X 3014 プログラム言語C++
5.17 代入演算子
<略> 代入演算の結果は、代入が行われた後の左の演算対象に格納された値とする。

JIS X3010 プログラム言語C
__6.5.16 代入演算子 __
<略> 代入式は,代入後の左オペランドの値をもつが,左辺値ではない

投稿2020/11/16 23:12

thkana

総合スコア7703

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

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

0

いい加減なコードで質問されてもちゃんとした説明をつけることはできません。

次のコードなら dynamic_cast について説明できます。

C++

1#include <iostream> 2#include <vector> 3 4using namespace std; 5 6class Base { 7public: 8 char esc; 9 Base() : esc('E') { } 10 virtual ~Base() { } 11 void print() { cout << "esc = " << esc << endl; } 12}; 13 14class A : public Base { 15public: 16 char lineKind; 17 A() : lineKind('A') { } 18 void print() { cout << "lineKind = " << lineKind << endl; } 19}; 20 21class B : public Base { 22public: 23 char lineKind; 24 B() : lineKind('B') { } 25 void print() { cout << "lineKind = " << lineKind << endl; } 26}; 27 28 29int main() 30{ 31 vector<Base *> bases; 32 A *ap; 33 B *bp; 34 35 bases.push_back(new A()); 36 bases.push_back(new B()); 37 38 for (vector<Base *>::iterator it = begin(bases); it != end(bases); ++it) { 39 if (ap = dynamic_cast<A *>(*it)) { 40 (*it)->print(); 41 ap->print(); 42 } 43 else if (bp = dynamic_cast<B *>(*it)) { 44 (*it)->print(); 45 bp->print(); 46 } 47 else 48 cout << "error\n"; 49 } 50 for (vector<Base *>::iterator it = begin(bases); it != end(bases); ++it) 51 delete *it; 52}

bases は Base * の vector であり、
Base の派生クラスである A や B へのポインタ を入れることができます。

ところが、メンバ関数 print は virtual ではなく、
それぞれのクラスの独自データを表示するだけのものです。
*it は Base * であり、(*it)->print() では Base のデータしか表示できません。

そこで、*it を派生クラスへのポインタにキャストして、
それぞれのクラスのデータを表示させることにします。

dynamic_cast により正しくキャストできた場合はその派生クラスへのポインタが
入りますが、そうでなければ nullptr になります。
if文では、キャスト結果が nullptr かどうかをチェックしています。

追記
dynamic_cast の問題ではなく、if文の式に代入式が使用された場合の意味が
分からないという質問ですか?

次のコードの意味も分かりませんか?

C

1#include <stdio.h> 2#include <string.h> 3 4int main() 5{ 6 char buf[1024], *p; 7 int len; 8 while (fgets(buf, sizeof buf, stdin)) { 9 if (p = strchr(buf, '\n')) 10 *p = '\0'; 11 if (len = strlen(buf)) 12 printf("len('%s') = %d\n", buf, len); 13 else 14 puts("empty line"); 15 } 16}

投稿2020/11/16 14:35

編集2020/11/16 14:54
kazuma-s

総合スコア8224

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

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

actorbug

2020/11/16 14:46

Baseにvirtualデストラクタがないと、A,Bのデストラクタが呼ばれないのでは
kazuma-s

2020/11/16 14:53

そうですね。間違って、virtual void hoge() {} なんて書いてしまいました。 回答を修正します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問