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

#はじめに
今日は、新しい単元に進まず、復習と再確認をやっていこうと思う。てか、やらなきゃ私の頭がパンクする。
23日目あたりから。

##uniform initialization
###uniform initializationとは
「一様初期化 (uniform initialization)」は、コンストラクタの呼び出しを、リスト初期化と合わせて波カッコ { }で記述する構文である。
[C++日本語リファレンス](https://cpprefjp.github.io/lang/cpp11/uniform_initialization.html)
###std::initializer_list
初期化子リストという。
動的配列`std::vector`を初期化するときはこのようにする。

```cpp
std::vector<int> a{}; 
```
最初から箱を作っておくための初期化方法は

```cpp
std::vector<int> a(10);//箱を10個作って初期化
```
また、数字をもとから入れて初期化する方法は

```cpp
std::vector <int> a {5,2,7,8,3};
```
[参照](https://qiita.com/h2suzuki/items/d033679afde821d04af8)

##char型
###const char*の意味
const char* の変数は、定数データへのポインタです。**中身の変更不可、アドレスの変更可**です。
###char* constの意味
char* const の変数は、定数ポインタです。**中身の変更可、アドレスの変更不可**です。
###const char* const
const char* const の変数は、定数データへの定数ポインタです。中身の変更不可、アドレスの変更不可です。
[参照](https://www.hiramine.com/programming/c_cpp/constcharconst.html)
とてもわかりやすいサイトでした。

>int const * const * const ** const * p;

以前の記事（23日目）でコメントで書いてくださったコードなんですが、
`int* const`と`int const*`は同じ意味で、「アドレスは変えられないが、中身は変えられるということ」
なので、`int***** const const const const p`になる？
たぶん、意味は、アドレスは変えられないが中身は変えらる」。

##見える 見えない
###スコープ解決演算子
`クラス名::メンバ名`でメンバを呼べるのは、なんらかの基底クラスを継承したクラスで、明示的に基底クラスや派生クラスのメンバにアクセスする場合（オーバーライドされているかどうかは関係ない。自分自身のメンバもこの方法で呼べる）と、そのメンバが静的メンバであった場合のみである。
**静的メンバ変数とは**

>これまで、クラス型のオブジェクトには全てのメンバが割り当てられました。
オブジェクトごとにメンバ変数が割り当てられ、メンバ変数はオブジェクト間で関係ありません。
しかし、あるクラスの全てのオブジェクトが、一つの変数を共有したいとすれば、困ります。
グローバル変数を使うこともできますが、それはオブジェクト指向プログラムに反した行為です。
そのような場合は、静的メンバ変数を用います。
静的メンバ変数は、全てのオブジェクトが共有するクラス内グローバル変数と呼べます。
これは、オブジェクトごとにコピーが作られるようなことはなく。
つねにクラスに一つしか存在しないメンバなのです。

つまり同じクラスで生成したインスタンスで、共通したメンバってことか。
PS４の例でいうと、「友達のPS4と自分のPS4のセーブデータをクラウドで共有する」といった感じだと思います。

静的メンバ変数の宣言には static キーワードを使う。
[参照](http://wisdom.sakura.ne.jp/programming/cpp/cpp41.html)

**静的メンバとthisの関係**
>メンバ関数からメンバ変数にアクセスするには、thisという、自分自身のクラスを指す特殊なポインタを利用します。これは暗黙のうちにメンバ関数を呼び出すときに0番目の引数として渡されています。

[参照](https://qiita.com/yumetodo/items/b0ff58617f2733d4ffa1#%E9%9D%9Estatic%E3%81%A7%E9%9D%9Evirtual%E3%81%AA%E3%83%A1%E3%83%B3%E3%83%90%E9%96%A2%E6%95%B0%E3%82%92%E6%8C%81%E3%81%A6%E3%82%8B)

###２つのコードの違い

```cpp
#include <iostream>
#include <memory>
struct A {
    virtual void f() { std::cout << "A" << std::endl; }
};
struct B : A {
    virtual void f() override { std::cout << "B" << std::endl; } 
    void g() { A::f(); }
};

int main()
{
    auto b = std::make_unique<B>();
    b->g();// => A
}
```

```cpp
#include <iostream>
namespace foo{
    void f() { std::cout << "foo::f" << std::endl; }
}
int main()
{
    foo::f();
}
```
`::`を使えばどこでも、好きなメンバを呼び出せると考えていたがそれは違う。
mainの中でB::g()と呼べるわけではない。
クラスのメンバはインスタンスを通してではないと使えない(見えない)。
つまり、`b`は`B`のインスタンスではなく、`B`を入れているだけなので、`b::g()`とできない。
インスタンスがないときに、`->`を使って、`b->g()`で`g()`を呼び出している。

と思っていたが、違うかもしれない。
もう少し考えてみる。

###PS４で例えた見える見えない。
この例は非常にわかりやすかったので、こちらの記事でも紹介さしてもらいます。
まるまるコピペします。

たとえ話はあまり好きではありませんが、例えば PS4 を Game という名前空間でクラスにしたとして、そこにゲームを始めるというメンバ関数があったとします。

```cpp

namespace Game {
    class PS4 {
        public:
            void play() { ... }
    }
}
```
この時、このPS4クラスにグローバル空間にあるmainからアクセスするためには、Game::PS4とスコープ解決演算子で名前空間を指定する必要があります。そうでないと、mainはどこからPS4クラスを見つけてくればいいかわからないのです。
これは、スコープ解決演算子がついていないあらゆる識別子（関数の場合はシグネチャ）は、ローカル変数、関数なら引数、その場所と同じかより外側にある名前空間1にあるクラス、関数、グローバル変数、クラス関数の定義の中であればそのクラスのメンバ、からしか探されない、という仕様によるものです（正確に規格になんて書いてあるかは存じません。）。したがって、mainの中でただPS4と書いても、mainのある空間であるグローバル空間（グローバル空間には外側に空間がないのでこれだけです）内しか「見え」ないため、見つからないのです。そのためにスコープ解決演算子でGame名前空間を指定しておくと、Game名前空間はグローバル空間に存在してmainから「見える」ので、じゃあそのGame名前空間からPS4を探そう、とやってくれるわけですね。
さて、ではGame::PS4::play()とできるか、という話ですが、これはできません。なぜでしょう。ちゃんというなら、メンバ関数は「どのインスタンスで実行されようとしているか」という情報が必要なので、インスタンスを介さないと呼べないのです。たとえ話で言うと、世界には PS4 は山ほど存在しているわけですから、単にGame::PS4::play()と呼んでも、どの PS4 でゲームを起動すればいいのかわからないわけです。

```cpp
int main() {
    // この PS4 はうちにあるもの！
    Game::PS4 myPS4;
    // 「うちの PS4」で遊ぶ！
    myPs4.play();
}
```
と「どの PS4」かをインスタンス化してやることで、初めて「その PS4」でゲームできるわけですね（ちゃんと言うと、インスタンスを介してメンバ関数を呼ぶことで、そのメンバ関数にthisが渡される。）。
ものすごくざっくりとした説明でしたが、とにかく、クラスのメンバは、たとえスコープ解決演算子を用いても、

・そのメンバが静的である場合
・その場所がそのクラスのメンバ関数の定義の中である場合

でなければ呼べません。それは、抽象的に言うなら「見え」ないからですが、ちゃんと言うなら、メンバへのアクセスに必要不可欠なthisが存在しないからです。


#終わりに
まだ復習は終わってないけど、眠いので寝ます。
明日は、復習と通常同里にすすめていけたらなと思っています。