C++ 継承のprivate / protected / publicの切り替え

# アクセス権限の意味
アクセス指定子をつけると設定できる

## `private`
該当する関数または変数には，それらが実装されたクラス（のメソッド）のみアクセスできる

## `protected`
該当する関数または変数には，それらが実装されたクラス（のメソッド）とそのクラスから派生したクラス（のメソッド）のみアクセスできる

## `public`
制限はない，オブジェクトを無から生成して渡すために`public`の関数を経由する必要がある



# アクセス権限の規制
継承時にアクセス指定子をつけると継承元の関数または変数のアクセス権限にリミットがかかる
隠蔽する方向にのみ動作する

## `private`
`public`と`protected`が`private`になる
```c++
class A{
    private:
        int x; // can't acccess from B
    protected:
        int y;
    public:
        int z;
}

class B:private A{
    // y -> private
    // z -> private
}
```

## `protected`
`public`が`protected`になる
```c++
class A{
    private:
        int x; // can't acccess from B
    protected:
        int y;
    public:
        int z;
}

class B:protected A{
    // y -> protected
    // z -> protected
}
```

## `public`
制限はない
```c++
class A{
    private:
        int x; // can't acccess from B
    protected:
        int y;
    public:
        int z;
}

class B:private A{
    // y -> protected
    // z -> public
}
```



# アクセス権限の変更
`using`と`::`でスコープをつけながらエイリアスを作成する際，アクセス指定子を先頭につければ個別に上書きできる

## 昇格
`protected`から`public`にする
```c++
class A{
    protected:
        int x;
}

class B:public A{
    public using A::x;
    // reachable A.x from public, protected, private
}
```
### 使い道
特に思いつかないし，こんなものが必要になるような場面に遭遇したら，ひとまず設計を修正した方が良い気がしています
### 一括で昇格させる方法
これがどうやら存在しないらしい．やるならば全てに一対一で`public using Class::name`を叩く必要があるらしい

## 降格
`public`から`protected`にする
```c++
class A{
    public:
        int x;
}

class B:public A{
    protected using A::x;
    // reachable A.x from protected, private
}
```
`public`から`private`にする
```c++
class A{
    public:
        int x;
}

class B:public A{
    private using A::x;
    // reachable A.x from private
}
```
`protected`から`private`にする
```c++
class A{
    protected:
        int x;
}

class B:public A{
    private using A::x;
    // reachable A.x from private
}
```
### 使い道
部分的に`protected`を`private`にしたいです，特に組込実装ではコード領域すらも節約する必要があるかと思います
### 一括で降格させる方法
つまり継承時にアクセス権限の規制をやれということで



# 多重継承
名前衝突や菱形問題の原因になるのでやめたい
もしくはせめて仮想継承をちゃんと実装したい

## 名前衝突
衝突しなかったらスコープ無しで派生クラスから呼べる
衝突したらスコープ派生元クラスを解決する必要がある
もし衝突してもエイリアスの作成は1個までならセーフ
```c++
class A{protected:int x;};
class B{protected:int x;};
class C:public A, public B{
    public: using A::x; // -> OK
    // public: using B::x; -> error
};

int main(void){
    C c;
    c.x = 0;
}
```
言い換えれば権限の変更は1個しかできないということ
むしろ今までのケースが「衝突しなかったらスコープ無しで派生クラスから呼べる」のを悪用して同名の再定義をしている

## 菱形問題
これらの例は`A`と`B`にそれぞれ独立に`x`があった上で`C`に合体させたせいで詰んでいるが，`x`を持つ`A`から`B`と`C`に派生させた上で`D`に合体させるような場合，（`B`と`C`が悪さをしない限り）仮想継承で`x`は何とかなるかも



# 仮想継承
```c++
#include <iostream>
using namespace std;

class A{
    protected:
      int x;
};

class B: virtual public A{};

class C: virtual public A{};

class D: public B, public C{
    private: using C::x;
    protected: using B::x;
    public: using A::x;
    // both lines are equivalent in operation (why?)
    // `public` is needed to be specified in the end
};


int main(void){
    D d;
    d.x = 1;
    //d.A::x = 1; -> error if A::x is placed in protected
    cout << d.x << endl;

};
```
`A::x`の実体を`B::x`も`C::x`も`D::x`も指すが，アクセス権限は`A::x`と`B::x`と`C::x`と`D::x`でそれぞれ設定され，かつ`using`でエイリアスを作成するとその都度に設定が上書きされる（これでも実体は1つなので問題ない）
最終的に`D`で`public: using`すると`D.x`を介して実体を操作できる