[C++]コンストラクション関数とレプリケーション制御

7694 ワード

文書ディレクトリ
  • 1ベースクラス構築関数およびレプリケーション制御
  • 2派生クラス構築関数
  • 2.1合成派生クラスデフォルトコンストラクタ
  • 2.2デフォルトコンストラクタの定義
  • 2.3伝達パラメータをベースクラス構築関数
  • 2.4派生クラス構築関数でデフォルトのパラメータ
  • を使用
  • 2.5直接ベースクラスを1つのみ初期化
  • 3コピー制御と継承
  • 3.1派生クラスのコピー構築関数
  • 3.2派生クラスの付与オペレータ
  • 3.3派生クラスの構造関数
  • 4仮想構造関数
  • 派生クラスオブジェクトの作成、コピー、割り当て、破棄について、派生クラスの構築関数です.
    1ベースクラス構築関数とレプリケーション制御
    コンストラクション関数は、protectedまたはprivateであり、一部のクラスでは、コンストラクション関数をprotectedと定義し、その派生クラスにのみ使用されます.
    2派生クラス構築関数
    2.1合成された派生クラスのデフォルト構造関数
    各派生クラスのコンストラクション関数は、ベースクラスを初期化し、独自のデータ・メンバーを初期化します.派生クラス合成のデフォルトの構造関数と一般的な合成の構造関数の違いは、派生クラスのデータ成語を初期化するだけでなく、ベースクラスのデータメンバーも初期化することです.
    ベースクラス:
         class Item_base {
         public:
             Item_base(const std::string &book = "", double sales_price = 0.0):
                              isbn(book), price(sales_price) { }
             std::string book() const { return isbn; }
             virtual double net_price(std::size_t n) const { return n * price; }
             virtual ~Item_base() { }
         private:
             std::string isbn;
         protected:
             double price;
         };
    

    派生クラス:
         class Bulk_item : public Item_base {
         public:
             double net_price(std::size_t) const;
         private:
             std::size_t min_qty;
             double discount; 
          };
    
    Bulk_itemクラスの場合、合成のデフォルト構造関数は次のように実行されます:1.Item_baseのデフォルトコンストラクタが呼び出されます.このデフォルトコンストラクタでは、isbnメンバーが空の文字列に初期化され、priceメンバーが0になります.2.一般変数初期化ルールを使用してBulk_itemのメンバーを初期化します.つまり、メンバーqtyおよびdiscountは初期化されません.
    2.2デフォルトのコンストラクタの定義Bulk_itemには組み込みタイプのメンバーがいるため、デフォルトコンストラクション関数をカスタマイズする必要があります.カスタムデフォルトコンストラクション関数は次のとおりです.
         class Bulk_item : public Item_base {
         public:
             Bulk_item(): min_qty(0), discount(0.0) { }
         };
    

    このデフォルトコンストラクション関数は、Item_baseのデフォルトコンストラクション関数を暗黙的に呼び出してベースクラス部分を初期化します.
    このコンストラクション関数を実行する効果は、まず、item_base部分がitem_baseのデフォルトコンストラクション関数によって初期化され、すなわちisbnが空文字列とされ、price0とされ、item_baseのデフォルトコンストラクション関数の実行が終了すると、Bulk_itemのメンバーが初期化され、コンストラクション関数の関数体(ここでは空)が実行されることである.
    2.3ベースクラス構築関数へのパラメータの伝達
    派生クラスのコンストラクション関数は、一般的に派生クラスのメンバーのみを初期化します.ベースクラスのメンバーの初期化は、ベースクラスを呼び出すコンストラクション関数で間接的に実現されます.
         class Bulk_item : public Item_base {
         public:
             Bulk_item(const std::string& book, double sales_price,
                       std::size_t qty = 0, double disc_rate = 0.0):
                          Item_base(book, sales_price),
                          min_qty(qty), discount(disc_rate) { }
          };
    

    2.4派生クラス構築関数でのデフォルトパラメータの使用
    この部分は読めなかったので、codeが間違っているのではないかと疑っています.
    Of course, we might write these two Bulk_item constructors as a single constructor that takes default arguments:
         class Bulk_item : public Item_base {
         public:
             Bulk_item(const std::string& book, double sales_price,
                       std::size_t qty = 0, double disc_rate = 0.0):
                          Item_base(book, sales_price),
                          min_qty(qty), discount(disc_rate) { }
             // as before
          };
    

    Here we provide defaults for each parameter so that the constructor might be used with zero to four arguments.
    疑いbooksales_priceはいずれも価値があるが、本のcodeはこのように書かれている.
    2.5直接ベースクラスは1つのみ初期化可能
    クラスA派生クラスB、クラスB派生クラスCを仮定すると、初期化時にC初期化BB初期化Cが初期化される.
    ≪リビルド|Rebuild|emdw≫:操作やデータの追加/削除などの操作でクラスを再設計することをリビルドと呼びます.
    3制御と継承のコピー
    ポインタが含まれていない限り、合成された操作が一般的に使用されます.逆に、レプリケーション制御をカスタマイズする必要があります.
    3.1派生クラスのコピー構築関数
    派生クラスがレプリケーションコンストラクタまたは付与オペレータを明示的にカスタマイズすると、デフォルトのレプリケーションコンストラクタまたは付与オペレータは完全に上書きされます.派生クラスのレプリケーションコンストラクタと付与オペレータは、ベースクラスと自分のクラスのデータのレプリケーションまたは付与を担当します.
    派生クラスが独自のレプリケーションコンストラクタを定義する場合、レプリケーションコンストラクタは、通常、オブジェクトのベースクラス部分を初期化するためにベースクラスのレプリケーションコンストラクタを明示的に使用する必要があります.
    class Base { /* ... */ };
    class Derived: public Base {
    public:
        // Base::Base(const Base&) not invoked automatically
        Derived(const Derived& d): Base(d) { /*... */ }
    };
    

    初期化関数Base(d)派生オブジェクトdをベースクラス部分の参照に変換し、ベースクラスのレプリケーションコンストラクタを呼び出します.ベースクラスの初期化関数を省略した場合:
     // probably incorrect definition of the Derived copy constructor
     Derived(const Derived& d) /* derived member initizations */
                                       {/* ... */ }
    

    その結果、ベースクラスのデフォルトのコンストラクション関数が呼び出され、オブジェクトのベースクラス部分が初期化されます.派生クラスメンバーを初期化するときにdから対応する要素がコピーされたと仮定すると、新しく構築されたオブジェクトは不思議です.ベースクラスの部分値がデフォルト値で、派生クラスメンバーの値が別のオブジェクトに割り当てられています.(?? )
    3.2派生クラスの割り当てオペレータ
    割り当てオペレータは、レプリケーションコンストラクタと似ています.派生クラスが独自の割り当てオペレータを定義している場合、この割り当てオペレータは、ベースクラスの部分を表示的に割り当てる必要があります.
    // Base::operator=(const Base&) not invoked automatically
    Derived &Derived::operator=(const Derived &rhs)
    {
        if (this != &rhs) {
            Base::operator=(rhs); // assigns the base part
            // do whatever needed to clean up the old value in the derived part
            // assign the members from the derived
        }
        return *this;
    }
    

    3.3派生クラスの構造関数
    構造関数は、レプリケーション構造関数および付与オペレータとは異なります.派生クラスの構造関数は、ベースクラスオブジェクトメンバーの破棄を担当しません.コンパイラは、派生クラスオブジェクトのベースクラス部分の構造関数を常に暗黙的に呼び出します.各構造関数は、自分のクラスのメンバーのクリーンアップのみを担当します.
    class Derived: public Base {
    public:
        // Base::~Base invoked automatically
        ~Derived()    { /* do what it takes to clean up derived members */ }
    };
    

    オブジェクトが破棄される順序は、構築される順序とは逆です.派生クラスの構造関数は、最上位のベースクラスまで実行されます.
    4仮想構造関数
    ベースクラス部分の構造関数は自動的に呼び出され,これはベースクラスの設計に重要な影響を及ぼす.deleteが動的に割り当てられたオブジェクトへのポインタを指す場合、構造関数は、オブジェクトが占有するメモリ領域を解放する前に、オブジェクトをクリーンアップするために実行されます.継承アーキテクチャ内のオブジェクトを処理する場合、ポインタの静的タイプは削除されたオブジェクトの動的タイプとは異なり、実際に派生クラスオブジェクトを指すベースクラスタイプポインタである可能性があります.
    もし私たちdeleteがベースクラスを指すポインタであれば、ベースクラスの構造関数が実行され、ベースクラスのメンバーがクリーンアップされます.オブジェクトが実際に派生クラスタイプである場合、動作は定義されません.正しい構造関数が実行されることを保証するために、ベースクラスの構造関数は仮想でなければなりません.
    class Item_base {
    public:
        // no work, but virtual destructor needed
        // if base pointer that points to a derived object is ever deleted
        virtual ~Item_base() { }
    };
    

    構造関数が仮想的である場合、ポインタによって呼び出されると、どの構造関数を呼び出すかは、ポインタが実際に指すオブジェクトのタイプによって異なります.
         Item_base *itemP = new Item_base; // same static and dynamic type
         delete itemP;          // ok: destructor for Item_base called
         itemP = new Bulk_item; // ok: static and dynamic types differ
         delete itemP;          // ok: destructor for Bulk_item called
    

    他の仮想関数と同様に、構造関数の仮想特性が継承されるため、ルートクラスの構造関数が仮想である場合、派生クラスの仮想関数も仮想である.
    **コンストラクション関数および付与*非*delete**
    構造関数のみが仮想として定義できます.コンストラクション関数は許可されません.コンストラクション関数が実行されると、オブジェクトが完全に構築されていないため、オブジェクトのダイナミックタイプが不完全になります.
    基本クラスでは、仮想オペレータvirtualメンバー関数を定義できますが、派生クラスで使用される付与オペレータには影響しません.各クラスには、独自の割り当てオペレータがあります.派生クラスの付与オペレータのパラメータクラス自体.
    クラス割り当てオペレータを=と定義すると、困惑し、役に立たない可能性があります.
    #5コンストラクション関数とコンストラクション関数の仮想化
    コンストラクション関数の実行時、またはコンストラクション関数の実行時にオブジェクトが不完全であることを議論し、コンストラクション関数またはコンストラクション関数で仮想関数を呼び出す問題について議論しましたが、大きな紙面は分かりませんでしたが、私はこのような関数を書くことはできません.
    以上はC++Primerが見ながら作った翻訳です.
    [1]C++ Primer 15.4 Constructors and Copy Control [2]https://stackoverflow.com/questions/9979194/what-is-constructor-inheritance [3]https://stackoverflow.com/questions/6178771/inheritance-and-constructors/6178801