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

#はじめに
明日からブラックジャック作ってみる。まだ何を基底クラスにすればいいのかとか曖昧なこと多いけど、まぁやってみる。
ソースコードは、ネットに沢山乗っていそうだけど、何も見ないで作ってみる。

##ロベールのC++
###昨日のコードに```override```をつけてみる
```Stream.h
#ifndef STREAM_H_
#define STREAM_H_

//0以上の値を順次取得していく処理行うための基底クラス
class Stream {
public:
  double Get() const;//設定された値を取得
  virtual bool Set();
public:
  double m_n; //現在の値
};
#endif
```

```Stream.cpp
#include "Stream.h"
#include <iostream>
//設定された値を取得
double Stream::Get() const {
  return m_n;
}
//値を設定
bool Stream::Set() {
  std::cout << "Stream::Set" << std::endl;
  m_n = -1;
  return false;
}
```

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

#include "Stream.h"

//入力クラス
class InputStream :
  public Stream
{
public:
  bool Set() override; //入力関数 //overrideを追加
};

#endif
```

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

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

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

#include "Stream.h"

class ArrayStream :
  public Stream
{
public:
  ArrayStream(const double* array);
  bool Set() override; //新しい値を設定

private:
  const double* m_array;//配列
  int m_i; //現在のインデックス
};

#endif
```

```ArrayStream.cpp
#include "ArrayStream.h"

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

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

bool Average(Stream & 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() {
  InputStream istream;
  Average(istream);

  static const double ARRAY[] = {0.5, 1.5, -1};
  ArrayStream astream(ARRAY);
  Average(astream);
}

```
<img width="489" alt="スクリーンショット 2019-03-21 1.05.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/298612/8de48897-de70-8815-ea83-a6905418e007.png">
コンパイルしたらwarningでてきた。
<img width="490" alt="スクリーンショット 2019-03-21 1.05.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/298612/273da158-3f1f-87f9-e16d-4f20bb8f96b3.png">
正常に実行できたので大丈夫であろう。
無事オーバーライドできました。

あと、アップキャストについて調べていたら```ダウンキャスト```というもを見つけた。
アップキャストは安全だがダウンキャストは危険とのこと。
少し解説みたら、アップキャストを本当の意味で理解できたかもしれない。

アップキャストは、（派）が（基）に情報を送り、その情報をもとに（基）がどの（派）の関数を使うか決めている。
ダウンキャストは、(基)が（派）に直接支持を出すので、明示的にキャストをしなければならない。

###07-05 オーバーライドと仮想関数(2)
仮想関数は基底クラスのメンバ関数から読んだ場合などでも本来の型に応じて呼び分けられる。

```Stream.h
#ifndef STREAM_H_
#define STREAM_H_

//0以上の値を順次取得していく処理行うための基底クラス
class Stream {
public:
  double Get() const;//設定された値を取得
  bool Set();
public:
  double m_n; //現在の値
protected:
  virtual void SetBase();
};
#endif
```

```Stream.cpp
#include "Stream.h"
#include <iostream>
//設定された値を取得
double Stream::Get() const {
  return m_n;
}
//値を設定
bool Stream::Set() {
  SetBase();
  return m_n >= 0;
}

//値を設定する基本関数
void Stream::SetBase(){
  std::cout << "Stream::SetBase" << std::endl;
  m_n = -1;
}
```

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

#include "Stream.h"

//入力クラス
class InputStream :
  public Stream
{
protected:
  void SetBase() override; //入力関数 //overrideを追加
};

#endif
```

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

//値を設定する基本関数
void InputStream::SetBase() {
  std::cin >> m_n;
}
```

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

int main() {
  Stream stream;

  stream.Set();
  std::cout << stream.Get() << std::endl;

  InputStream istream;

  std::cout << ">" <<std::flush;
  istream.Set();
  std::cout << istream.Get() << std::endl;
}
```
便利ですね。
#終わりに
明日はブラックジャックもやります。
おやすみなさい。