C++Primer読解心得(第七章)

6777 ワード

1.データ抽象とパッケージ:データ抽象はインタフェースと実装の分離に依存するプログラミング技術であり、ユーザーはインタフェースを理解するだけで使用でき、実装の詳細に関心を持たなくてもよい.カプセル化はクラスのインタフェースとインプリメンテーションの分離を実現し、ユーザーはインタフェースしか使用できず、インプリメンテーション部分にアクセスできない.
2.thisポインタの入力:クラスのメンバー関数に、コンパイラがこのように入力したthisポインタ(定数ポインタであることに注意し、ポインタを変更することは許されません)があります.
class A
{
    int function(int para);
}

int A::function(int para)  //         
{ ...... }

int A::function(A* const this, int para) //        
{ ...... }


A a;
a.function(100); //         
A::function(&a, 100); //        
3. constメンバー関数:constメンバー関数ではオブジェクトのデータの変更は許可されず、非constメンバー関数の呼び出しも許可されません(これはオブジェクトのデータを間接的に変更するため、C++で閉じられます).このような関数は次のように宣言されます.
class A
{
    int function(int para)  const; //     const    
    int function(const A *this, int para) //    const    
}

コンパイラはconst A*thisによってconstメンバー関数の動作を制御します.thisはconstを指すため、thisによってオブジェクトのデータを変更することはできません.しかしthisが隠れた後、constはどこにも置けなかったので、声明全体の最後に置かれました...
4.クラスは単独で1つの役割ドメインとなり、同じ役割ドメインのメンバー(データまたはメンバー)は、宣言の順序を気にすることなく直接アクセスできます.これは、クラスコードをコンパイルするときのコンパイラの特殊な動作によって決まります.コンパイラはクラスメンバー宣言をコンパイルしてから、メンバー関数体をコンパイルします.クラスの外部で定義されたメンバー関数:パラメータリストと関数体の内部はクラスの役割ドメインにあり、戻り値はクラスの役割ドメインにありません.ドメインで使用する場合は、追加の宣言が必要です.メンバー関数はメンバー関数のみをリロードできます.役割ドメインが異なるため、クラス以外の関数はリロードできません.クラスメンバー関数の変数の検索順序は、関数内->クラス内->グローバル
class A
{
public:
    typedef int pos;
    pos func(pos p);
};

A::pos A::func(pos p){}; //ok,                     ,      

5.コンストラクション関数をconstとして定義することはできません.コンストラクション関数が実行されると、このオブジェクトはまだ存在せず、constプロパティを取得できません.
6.デフォルトのコンストラクション関数:パラメータなしで呼び出すコンストラクション関数(パラメータなしの場合、すべてのパラメータにデフォルト値がある場合も!)オブジェクトがデフォルト初期化されたときに呼び出されるため、デフォルトコンストラクタと呼ばれます.クラスにコンストラクタがない場合、コンパイラはデフォルトコンストラクタを合成します.合成されたデフォルトコンストラクタは、クラス内の初期値を使用してメンバー変数を初期化します.クラス内の初期値がない場合は、クラス内の初期値を使用してメンバー変数を初期化します.値はデフォルトでメンバー変数を初期化します.c++11では、パラメータリストの後に=defaultを使用して、コンパイラにデフォルトの動作の構築関数を生成するように要求できます.
class A
{
    A(){} //      ,      
    A(int a=1, double b=1.0){} //      ,      
    A() = default; //                
};
注意:デフォルト動作のコンストラクション関数(=defaultまたは合成デフォルトコンストラクション関数)は、ポインタメンバーに対して「浅いコピー」の問題をもたらし、クラス内の初期値のないメンバーに対して未定義の値に初期化されることに注意してください.
7.初期化リスト:初期化リストの動作は、コンストラクション関数体が実行される前に、中に書かれたメンバー変数を初期化します.したがって、メンバー変数の初期化プロセスは次のとおりです.
初期化リスト->クラス内の初期値->デフォルト初期化(前の2つのステップにないメンバー変数はデフォルトで初期化されます)
したがって、コンストラクション関数体の内部のメンバー変数は初期化されており、それらに値を付けるしかありません.初期化リストの初期化順序は、クラス内のメンバー変数の宣言順序に従って初期化されるので、初期化リストで1つのメンバー変数を使用して別のメンバー変数を初期化する場合は、宣言順序の問題に特に注意してください.構造関数に対する初期化リスト:
  • は、いくつかの複雑なクラスに対して、より効率的に実行されます.コンストラクション関数では、メンバー変数が初期化されてから付与されるため、2回の操作が実行されます.
  • メンバー変数がデフォルトのコンストラクション関数のないクラスのオブジェクトである場合、初期化リストのみを使用して初期化できます.このメンバー変数はデフォルトで初期化できないため、コンストラクション関数に到達しないとエラーが発生します.
  • constメンバー変数および参照メンバー変数についても、初期化リストを使用してのみ初期化できます.一度だけ初期化できるので、デフォルトの初期化は私たちの目的を達成することはできません.

  • 8.デフォルトのコンストラクタに加えて、コンパイラはコピーコンストラクタ、=番号オペレータ、および構造関数を自動的に合成します.注:コンストラクション関数を定義すると、コンパイラはデフォルトのコンストラクション関数を合成しません.
    9.C++のクラスはアクセス制御子を通じてデータ抽象とカプセル化を提供し、publicはクラスのインタフェースを識別してデータ抽象を定義し、privateはクラスの実現の詳細をカプセル化した.クラスの定義では、同じアクセス制御子が複数回表示され、次の制御子またはクラス定義の最後まで機能します.
    10.C++のclassとstructの違いは、structのメンバーのデフォルトがpublicであり、classのデフォルトがprivateであることだけです.この点の違いだけで、他の特性はそっくりで、structは関数を含んでもよいし、継承、マルチステートを行ってもよい.
    11.クラス、クラスのメンバー関数、または通常の関数をクラスの友元として宣言できます.プライベートメンバーを含むすべてのメンバーにアクセスすることを許可します.友元に伝達性がないことに注意してください.また、リロードされた関数のセットを友元と宣言するには、それぞれ宣言しなければなりません(コンパイラでは異なる関数のように見えますから~).
    12.クラスの内部には、クラスに属するタイプの別名(typedefまたはusing)も定義できます.publicなどのアクセス制限子を使用して制限できます.また、他のメンバーとは異なり、別名は宣言後に使用する必要があります.宣言ビットを無視する待遇はありません.
    class A
    {
        public:
            typedef int pos1;
    
            pos2 b = 2; //  ,pos2   
            using pos2 = int;
        private:
            pos1 a = 1; //ok
    };
    
    pos1 aa = 1; //  ,pos1   
    A::pos2 bb = 2; //ok
    13. クラス内に定義されたメンバー関数は自動inlineです.
    14.可変データ・メンバー:データ・メンバーをmutableとマークすると、そのデータ・メンバーは可変データ・メンバーとなり、constメンバー関数でもデータ・メンバーを変更できます.
    15.不完全なタイプ:定義のみを宣言または完了していない(定義中)のクラスは不完全タイプと呼ばれ、不完全タイプは参照またはポインタを定義するためにのみ使用されます.定義されていないタイプまたは定義されていないタイプでは、コンパイラはそのオブジェクトにどれだけのメモリが必要か分からないため、そのタイプのオブジェクトを定義できません.ただし、アドレスの大きさはOKなので、そのオブジェクトへのポインタまたは参照を定義できます.例:
    class screen;  //     
    
    class screen
    {
       ...
       screen* ps;  //   ,screen       ,       
       ...
    };
    クラスには、クラスの定義が完了するまで不完全なタイプであるため、独自のポインタまたは参照しか含まれません.(なるほど!)
    16.委託構造関数:c++11には委託構造関数のメカニズムが追加され、1つの構造関数は他の構造関数を使用して初期化プロセスを完了することができる.
    class A
    {
    public:
        A(int a, int b, int c):m_a(a),m_b(b){m_c=c}
        A(int a):A(a,0,0){cout<<"Delegating done!"<<endl;} //      
    private:
        int m_a;
        int m_b;
        int m_c;
    }
    依頼コンストラクション関数の実行順序:依頼コンストラクション関数の初期化リスト->依頼コンストラクション関数の関数体->依頼コンストラクション関数の関数体
    17.暗黙クラスタイプ変換:パラメータを持つ構造関数であり、「変換構造関数」とも呼ばれます.コンパイラは状況に応じて暗黙的に実パラメトリックオブジェクトをクラスに変換するオブジェクトを呼び出すからです.注:暗黙的なクラスタイプ変換は一歩のみ行われます.
    string str1 = "abc";
    string str2 = str1 + "bcd"; //      ,"bcd"       string    str1   
    では、暗黙的なタイプ変換が私たちの目的から逸脱する場合があります.この場合、explicitキーワードを使用して抑制することができます.explicitキーワードで修飾された単一パラメトリック構造関数は暗黙的に呼び出すことはできませんがstatic_を使用します.castが表示できる呼び出し.
    class A
    {
    public:
        explicit A(string s){}
    }
    
    A a = string("abc"); //  ,      
    A a = static_cast<A>(string("abc")); //ok,    
    18. 集約クラス:cスタイルのstructは「集約クラス」と呼ばれます.c++11は、対応する構造関数を記述する必要がなく、リストを使用して集約クラスを初期化することを可能にする.(コンパイラの特別な配慮?)
    struct A
    {
        int b;
        string s;
    };
    
    A a = {1,"abc"} //ok
    19. constexprコンストラクション関数:コンストラクション関数はconstではありませんが、constexprであってもよいです.constexprはこの関数が返す定数式を表し,このクラスのオブジェクトが文字面値であれば要求を満たすことができるので,構造関数自体の定義と矛盾しない.一方、constexprは関数体にreturn文が1つしかないことを要求し、構造関数は関数体にreturn文がないことを要求し、したがってconstexprコンストラクション関数の関数体は空(=defaultを使用してもよい)のみであり、初期化リストを使用してデータメンバーを初期化するしかありません.constexprコンストラクション関数はすべてのデータメンバーを初期化する必要があります.そうしないと、生成されたオブジェクトはフォント値オブジェクトの要件を満たしません.
    class A
    {
    public:
        constexpr A(int a, double b, bool c):m_a(a),m_b(b),m_c(c){}
    private:
        int m_a;
        double m_b;
        bool m_c;
    }

    constexpr:constexprをまとめると、コンパイル期間中にその値を決定する定数、定数関数を定義することができ、コンパイラはそれらが変更されないことを保証するので、constexpr式は一般化され、保証された定数式です.constexprが変数に作用するとconstexpr定数が得られ、constexprが関数に作用するとconstexpr関数が得られ、constexprが構造関数に作用すると字面値定数クラス(constexpr構造関数を有し、メンバー変数はいずれも字面値(内蔵タイプまたは字面値定数クラス)、デフォルトの解析関数のみ)が得られる.
    20.staticメンバーはクラス自体に属し、いずれのクラスのオブジェクトにも属しません.staticデータメンバーはクラス定義で初期化できません.クラス定義の外でのみ初期化できます.constexpr staticデータ・メンバーは、クラス内の初期値を持つことができます(ただし、クラス外で定義する必要があります).staticメンバー関数はstaticデータ・オブジェクトおよび他のstaticメンバー関数にのみアクセスできます.staticで使用できるかどうかはstaticではわかりません.(クラスオブジェクトは初期化されていない可能性があります)、同理staticメンバー関数にもthisポインタはなく、constとして宣言することはできません.