[C++]コンストラクション関数とレプリケーション制御
7694 ワード
文書ディレクトリ1ベースクラス構築関数およびレプリケーション制御 2派生クラス構築関数 2.1合成派生クラスデフォルトコンストラクタ 2.2デフォルトコンストラクタの定義 2.3伝達パラメータをベースクラス構築関数 2.4派生クラス構築関数でデフォルトのパラメータ を使用2.5直接ベースクラスを1つのみ初期化 3コピー制御と継承 3.1派生クラスのコピー構築関数 3.2派生クラスの付与オペレータ 3.3派生クラスの構造関数 4仮想構造関数 派生クラスオブジェクトの作成、コピー、割り当て、破棄について、派生クラスの構築関数です.
1ベースクラス構築関数とレプリケーション制御
コンストラクション関数は、
2派生クラス構築関数
2.1合成された派生クラスのデフォルト構造関数
各派生クラスのコンストラクション関数は、ベースクラスを初期化し、独自のデータ・メンバーを初期化します.派生クラス合成のデフォルトの構造関数と一般的な合成の構造関数の違いは、派生クラスのデータ成語を初期化するだけでなく、ベースクラスのデータメンバーも初期化することです.
ベースクラス:
派生クラス:
2.2デフォルトのコンストラクタの定義
このデフォルトコンストラクション関数は、
このコンストラクション関数を実行する効果は、まず、
2.3ベースクラス構築関数へのパラメータの伝達
派生クラスのコンストラクション関数は、一般的に派生クラスのメンバーのみを初期化します.ベースクラスのメンバーの初期化は、ベースクラスを呼び出すコンストラクション関数で間接的に実現されます.
2.4派生クラス構築関数でのデフォルトパラメータの使用
この部分は読めなかったので、codeが間違っているのではないかと疑っています.
Of course, we might write these two Bulk_item constructors as a single constructor that takes default arguments:
Here we provide defaults for each parameter so that the constructor might be used with zero to four arguments.
疑い
2.5直接ベースクラスは1つのみ初期化可能
クラス
≪リビルド|Rebuild|emdw≫:操作やデータの追加/削除などの操作でクラスを再設計することをリビルドと呼びます.
3制御と継承のコピー
ポインタが含まれていない限り、合成された操作が一般的に使用されます.逆に、レプリケーション制御をカスタマイズする必要があります.
3.1派生クラスのコピー構築関数
派生クラスがレプリケーションコンストラクタまたは付与オペレータを明示的にカスタマイズすると、デフォルトのレプリケーションコンストラクタまたは付与オペレータは完全に上書きされます.派生クラスのレプリケーションコンストラクタと付与オペレータは、ベースクラスと自分のクラスのデータのレプリケーションまたは付与を担当します.
派生クラスが独自のレプリケーションコンストラクタを定義する場合、レプリケーションコンストラクタは、通常、オブジェクトのベースクラス部分を初期化するためにベースクラスのレプリケーションコンストラクタを明示的に使用する必要があります.
初期化関数
その結果、ベースクラスのデフォルトのコンストラクション関数が呼び出され、オブジェクトのベースクラス部分が初期化されます.派生クラスメンバーを初期化するときに
3.2派生クラスの割り当てオペレータ
割り当てオペレータは、レプリケーションコンストラクタと似ています.派生クラスが独自の割り当てオペレータを定義している場合、この割り当てオペレータは、ベースクラスの部分を表示的に割り当てる必要があります.
3.3派生クラスの構造関数
構造関数は、レプリケーション構造関数および付与オペレータとは異なります.派生クラスの構造関数は、ベースクラスオブジェクトメンバーの破棄を担当しません.コンパイラは、派生クラスオブジェクトのベースクラス部分の構造関数を常に暗黙的に呼び出します.各構造関数は、自分のクラスのメンバーのクリーンアップのみを担当します.
オブジェクトが破棄される順序は、構築される順序とは逆です.派生クラスの構造関数は、最上位のベースクラスまで実行されます.
4仮想構造関数
ベースクラス部分の構造関数は自動的に呼び出され,これはベースクラスの設計に重要な影響を及ぼす.
もし私たち
構造関数が仮想的である場合、ポインタによって呼び出されると、どの構造関数を呼び出すかは、ポインタが実際に指すオブジェクトのタイプによって異なります.
他の仮想関数と同様に、構造関数の仮想特性が継承されるため、ルートクラスの構造関数が仮想である場合、派生クラスの仮想関数も仮想である.
**コンストラクション関数および付与*非*
構造関数のみが仮想として定義できます.コンストラクション関数は許可されません.コンストラクション関数が実行されると、オブジェクトが完全に構築されていないため、オブジェクトのダイナミックタイプが不完全になります.
基本クラスでは、仮想オペレータ
クラス割り当てオペレータを
#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
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
が空文字列とされ、price
が0
とされ、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.
疑い
book
とsales_price
はいずれも価値があるが、本のcodeはこのように書かれている.2.5直接ベースクラスは1つのみ初期化可能
クラス
A
派生クラスB、クラスB派生クラスC
を仮定すると、初期化時にC
初期化B
、B
初期化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