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

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

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

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

Q&A

解決済

2回答

1690閲覧

クラスのコンストラクタ

hikar

総合スコア13

C++

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

0グッド

0クリップ

投稿2020/02/03 15:58

編集2020/02/03 16:02

C++

1#include <iostream> 2 3struct Rect { 4 float m_position; 5 float m_size; 6 7 Rect(float const& _position, float const& _size); 8 void Draw(); 9}; 10 11Rect::Rect(float const& _position, float const& _size) 12:m_position(_position) 13, m_size(_size) 14{} 15 16void Rect::Draw() { 17 std::cout << m_position << std::endl; 18 std::cout << m_size << std::endl; 19} 20 21Rect rect=Rect(100, 200); 22/***********デバックエラー 23Rect rect; 24rect.Rect(100, 200); 25**************************/ 26int main() { 27 28 rect.Draw(); 29 30 return 0; 31}

確認というかたちになってしまうかもしれませんが、
上のソースコード「Rect rect=Rect(100, 200);」の部分なのですが、
これは、構造体Rect(基底クラス?)を rect(派生クラス?)に引き継ぎ、rect=Rect(100,200)で初期化(代入)。ということでしょうか?私は
Rect rect;
rect.Rect(100, 200);
でやろうとしたのですが、エラーが出てしまいました。

Rect(float const& _position, float const& _size)
:m_position(_position)
, m_size(_size)

これは基底クラスのコンストラクタであって、派生クラスではつかえないということでしょうか?
このような考え方であっているのであれば、rect=Rect(100,200)の仕様がよくわかりません。
派生クラス内のコンストラクタはどのようになっているのでしょうか?
基底クラスと中身は同じで、rect内は

C++

1struct rect { 2 float m_position; 3 float m_size; 4 5 Rect(float const& _position, float const& _size); 6 void Draw(); 7};

このようになっているのでしょうか?
そして構造体rect(派生)とコンストラクタRectの型が合わずエラーが起きてしまう。
なので上記のようにrect=Rect(100,200)でrectクラス(派生)のRectに代入しているのでしょうか?
まったくの的外れだったらすみません。<(_ _)>

それとちなみに

Rect(float const& _position, float const& _size)
:m_position(_position)
, m_size(_size)

ここで使っている「&」はネットで調べたら、参照渡しとわかりましたが、これは今後必要なのでしょうか?

「&」:元の変数に別名をつける記法である(ここで使うの場合)

「&」がなくても引数の名前は変えられる気がしますが.....
「&」がなくてもデバック結果は変わりませんでした。

的外れのことを書いていたらすみません。<(_ )>
どなたかわかる方どうか教えてください<(
_)>

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

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

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

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

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

guest

回答2

0

これは、構造体Rect(基底クラス?)を rect(派生クラス?)に引き継ぎ、rect=Rect(100,200)で初期化(代入)。ということでしょうか?私は

Rect rect;
rect.Rect(100, 200);
でやろうとしたのですが、エラーが出てしまいました。

このやり方ではデフォルトコンストラクタがないので、出来ません。
やりたいならポインターを使ってnewするのが良いでしょう。

Rect *rect; rect = new Rect(100, 200);

このようになっているのでしょうか?

float a; a = .0f;

この場合、float型の変数「a」となります。同様にRect型の変数「rect」となります。
ですので、構造体もクラスも変数もインスタンスするという意味では同じ考え方になります。

投稿2020/02/04 01:56

stdio

総合スコア3307

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

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

hikar

2020/02/04 19:39

ご返信ありがとうございます。(>_<) 教えていただいたコードで正常に実行することができました。 newについてあまりよく調べてないので、これからしっかり勉強していきます。 またわからないことがあったら質問させていただきますので、よろしくお願いします。
guest

0

ベストアンサー

クラスは型です。
ここでは Rect は型であり、その型を元に生成されたオブジェクトを入れる場所が rect です。

そして

cpp

1Rect rect;

がエラーになるのはデフォルトコンストラクタが定義されていないからです。 デフォルトコンストラクタというのは引数がないコンストラクタです。 変数宣言のときに引数を渡さなければデフォルトコンストラクタで処理しようとします。 しかし呼び出すべきものがないのでエラーになります。 (自分でコンストラクタをひとつも定義しなければデフォルトコンストラクタは自動生成されます。)

rect=Rect(100,200)の仕様がよくわかりません。

クラスは型だと説明しましたが、 C++ のクラス名は常にそのクラスのコンストラクタと同じ名前を持ちます。 Rect(100,200)Rect 型のオブジェクトを生成する関数を呼び出していると考えてください。

Rect rect という宣言によって Rect 型の変数 rect が用意され、 Rect(100,200) という関数を呼び出した結果を rect に入れるという意味になっています。

rectRect(100,200) を入れるにあたってはコピーコンストラクタが呼ばれていて、これも自分で書かなければ自動生成されています。

参照渡しとわかりましたが、これは今後必要なのでしょうか?

はい。 絶対に必要です。

「&」がなくても引数の名前は変えられる気がしますが.....
「&」がなくてもデバック結果は変わりませんでした。

この場所で & を付けなかった場合、引数を渡した側の「コピー」になります。 同じものを別の名前で見るというのと、同じ内容のものがふたつあるというのとでは違うので使い分けが必要です。 必要もないのにコピーするのは実行速度も遅くなる可能性があります。

投稿2020/02/03 17:25

SaitoAtsushi

総合スコア5444

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

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

hikar

2020/02/04 09:22

ご返答ありがとうございました。とても分かりやすかったです。!(^^)! クラス内でコンストラクタを意図的に宣言しない場合はオブジェクト生成時にデフォルトコンストラクタが自動で生成されるが、 上のように自分で意図的にコンストラクタをクラス型内で定義した場合は、Rect rect;では自動的にコンストラクタが生成されないため、オブジェクト生成時に一緒にコンストラクタされるはずが、その元のコンストラクタがないてめ、エラーになってしまう。だから、Rect rect=Rect(100, 200);でオブジェクト生成時に意図的にコンストラクタを生成しなければならないということでよろしいでしょうか? そして、ここでのコンストラクタはクラス内の変数に初期値を設定してオブジェクトを生成というつかいかたでよろしいでしょうか? ちなみにに、クラス内でデフォルトコンストラクタを定義した場合は、 Rect rect; Rect(); これでできる。ということでしょうか? (クラス内で定義しなくても、オブジェクト生成時に自動で生成されるから定義しなくてもいい?) いただいた返答からこのように考えたのですが、間違えていたら嫌なので、確認で再度質問投稿になってしまうのですが、どうかよろしくお願いします。<(_ _)>
SaitoAtsushi

2020/02/04 10:55

関連する事柄が多いので全てをここで述べることはできません。 しかし、基礎なのでどんな入門書を読んでも理解できるように書いてあるはずです。 (もし書いていないなら単に出来の悪い教材です。) 大雑把には回答しますが、細かいことはきちんとした資料を読んでください。 > オブジェクト生成時にデフォルトコンストラクタが自動で生成される いいえ。 デフォルトコンストラクタはクラス定義時に暗黙に定義されたかように振舞います。 オブジェクト生成時にそれが「起動」します。 > Rect rect=Rect(100, 200);でオブジェクト生成時に意図的にコンストラクタを生成しなければ コンストラクタを起動して出来上がったオブジェクトを rect にコピーするということが起こっています。 Rect rect(100, 200); という書き方でも良いです。 こちらの書き方では生成してからコピーではなく、 rect の場所で 100 と 200 という引数と共にコンストラクタが起動するという形です。 rect の場所で直接的にコンストラクタが起動するので少し効率がよいかもしれません。 ただし、一部の状況ではコピーを抑制する最適化をしてもよいという仕様があり、 Rect rect=Rect(100, 200); を Rect rect(100, 200); と同じように解釈することがあります。 (従来はそのような最適化を許容する仕様でしたが、最新仕様では必須の挙動に変更されています。) > ここでのコンストラクタはクラス内の変数に初期値を設定してオブジェクトを生成というつかいかたでよろしいでしょうか? それでよいですが、定義するクラスの役割によっては初期値を設定する以外のことをすることもあります。 > 自動で生成されるから定義しなくてもいい? 自動で生成されるコンストラクタは一定のルールに則って処理するだけなので、クラスの性質によっては問題が生じることもあります。 自動生成されるコンストラクタで良いかどうかを判断するのはあなた次第です。
hikar

2020/02/04 19:32

ご返信ありがとうございました(>_<) すごくわかりやすく、完全に理解出来ました! またわからないことがあったら質問させていただきますので、よろしくお願いします。<(_ _)>
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問