はじめてのC++【17日目】

#はじめに
ゲームエンジン使わずにゴリゴリプログラムを書いて2Dゲームを作りたいなと考えていました。
まだ先になるかと思いますが、「はじめてのwiiのタンク」を作ることを決めました。
（参考https://youtu.be/IIaH8FCVwGg）
かなり難しいかもしれないがロベール終わったらやり始める。
##ロベールのC++
###06-08　コピーコンストラクタ
ロベールの本がよくわからなかったのでネットで学習

コピーコンストラクタも同様に、宣言しなかった場合はデフォルトコピーコンストラクタが生成される。
このコピーコンストラクタでメモリ確保を行い配列を複製する。

**コピーコンストラクタが存在する理由**
>メンバ変数に配列が含まれている場合、関数等にオブジェクトを値渡しするためにはコピーコンストラクタを用意する必要があります。用意せずに値渡しすると、配列の先頭アドレスの値だけがコピーされ複数のオブジェクトで共有されることになり、片方のオブジェクトが破棄される際のデストラクタ処理などでアドレスが参照する先の領域が解放されてしまう恐れがあるためです。

配列ってstd::arrayもstd::vectorも含まれてるのか。
これは危ないな。


**コピーコンストラクタが、呼ばれるタイミング**
>1.オブジェクトの初期化時
2.オブジェクトを関数に値渡しするとき
3.関数からオブジェクトを値渡しする時
まとめるとオブジェクトのコピーが行われたとき

**例**

```cpp
class Hello{
public:
  Hello(const Hello& other)  //コピーコンストラクタ
private
  int m_array[];
};

Hello::Hello(const Hello& other){
 m_array = new int[];//こんなかんじで新しくメモリ確保するみたい
}
```
（参考文献）
https://qiita.com/youthini/items/2314ad7cf498e5f199d7
https://www.qoosky.io/techs/a8ffeeeee6

###06-09 演算子オーバーロード

**宣言方法**

```cpp
class Hello {
public:
  void operator=(const Hello& other);
//略
};

void Hello::operator=(const Hello& other){
  int * array = new int [other.m_size] //これでも動的配列ができるみたい。std::vectorのほうがいいのだろうけど。
```

このようにして使う。
```operator=```を関数名のように扱う。

演算子オーバーロードは濫用するとプログラムが分かりづらくなるので限定的な状況を除いてはなるべく使わない。

###07-01　継承の基本

**継承とは？**
継承とは、あるクラスを基に新しいクラスを作ること。

```Average1.cpp
#include <iostream>

//入力関数
//0以上の値が入力されればtrue　負の数字はfalse
bool Input(double& n){
  std::cin >> n;
  return n >= 0;
}

//入力を受け取り平均値を求め,その値を出力する関数
//要素数が0の場合は何も出力せず、falseを返す
bool Average(){
  int count;
  double n;
  double avr = 0;

  for(count = 0; Input(n); ++count) {
    avr +=n;
  }
  if(count == 0){
    return false;
  }

  avr /= count; //この書き方初めてみた
  std::cout << "平均値は " << avr << " です。" << std::endl;
  return true;
}

int main(){
  while (Average()){

  }
}
```
<img width="179" alt="スクリーンショット 2019-03-13 23.14.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/298612/f4a81d53-84a3-6625-4272-3a51e26a4371.png">

上で書いたコードでクラスを作る。

```InputStream.h
#ifndef INPUTSTREAM_H_
#define INPUTSTREAM_H_

//入力するためのクラス
class InputStream{
public:
  double Get() const;//constメンバ関数...メンバ変数を変更しないメンバ関数
  bool Set(); //入力関数

private:
  double m_n; //入力された値
};

#endif
```

```InputStream.cpp
#include "InputStream.h"
#include <iostream>

double
InputStream::Get() const{
  return m_n;
}

//入力関数
bool
InputStream::Set(){
  std::cin >> m_n;
  return m_n >= 0;
}
```

```Average2.cpp
#include "InputStream.h"
#include <iostream>

bool
Average(InputStream& stream) {
  int count;
  double avr = 0;

  for(count = 0; stream.Set(); ++count) {
    avr += stream.Get();
  }

  if(count == 0){
    return false;
  }

  avr /= count;
  std::cout << "平均値は " << avr << "です。" << std::endl;
  return true;
}

int main(){
  while(true){
    InputStream stream;
    if(!Average(stream)){
      break;
    }
  }
}
```
これで、0以上の数の入力を順次受け付ける処理をクラスとして部品化できた。

次は、入力を確定したあとに入力ミスがあったことに気づいた場合に、配列を作りその平均を出力するプログラムを作る。

```ArrayStream.h
#ifndef ARRAYSTREAM_H_
#define ARRAYSTREAM_H_

#include <vector> //動的配列
//入力するためのクラス
class ArrayStream{
public:
  ArrayStream(const double* array);//コンストラクタってパブリックでいいんだよな
  double Get() const;//constメンバ関数...メンバ変数を変更しないメンバ関数
  bool Set(); //入力関数

private:
  //std::vector<double> m_array;//動的配列を宣言
  const double* m_array;
  int m_i;
  double m_n; //入力された値
};

#endif
```
```ArrayStream.cpp



#include "ArrayStream.h"
#include <iostream>
/*
ArrayStream::ArrayStream() : m_array{} {//コンストラクタで配列を初期化
}
*/

ArrayStream::ArrayStream(const double* array){
  m_array = array;
  m_i = 0;
}

//設定された値を取得
double
ArrayStream::Get() const{
  return m_n;
}

//入力関数
bool
ArrayStream::Set(){
  m_n = m_array[m_i];
  if(m_n >= 0){
    ++m_i;
    return true;
  }else{
  return false;
  }
}
```
```Average3.cpp
#include "ArrayStream.h"
#include <iostream>

bool
Average(InputStream& stream) {
  int count;
  double avr = 0;

  for(count = 0; stream.Set(); ++count) {
    avr += stream.Get();
  }

  if(count == 0){
    return false;
  }

  avr /= count;
  std::cout << "平均値は " << avr << "です。" << std::endl;
  return true;
}

int main(){
  static const double ARRAY1[] = { 1, 2, 3, -1};
  static const double ARRAY2[] = { 1.5, 0.5, -1};
  static const double ARRAY3[] = { -1 };
  static const double ARRAY[] = { ARRAY1, ARRAY2, ARRAY3};
  static const int SIZE = sizeof ARRAY / sizeof *ARRAY;

  for(int i = 0; i < SIZE; ++i){
    ArrayStream stream(ARRAY[i]);
    if(!Average(stream)){
      break;
    }
  }
}
```
継承の話まだ進んでないな。この節長すぎ。
ロベールでは普通の配列として書いているがそれを動的配列に書きす方法がよくわからなかった。
動的配列の復習は明日やる。

#終わりに
明日早いので早く寝る。
おやすみなさい。