c++オブジェクトをコピーするときは、その各部分を忘れないでください.
オブジェクト向けに設計されたシステムは、オブジェクトの内部をカプセル化し、オブジェクトのコピー(コピー)を担当する2つの関数だけを残します.これは、テスト名付きのcopyコンストラクション関数とcopy assignmentオペレータで、copying関数と呼ばれ、コピーされたオブジェクトのすべてのメンバー変数をコピーする「コンパイラ生成版」の動作を説明します.
自分のcopying関数を宣言すると、デフォルトの実装のいくつかの動作が好きではないことをコンパイラに伝えることを意味します.コンパイラは犯されたように、奇妙な方法で敬意を表します.実装コードがほとんど間違いを犯すと、教えてくれません.
コンパイラではなく手動でcopying関数を書き、外部からの呼び出しがログに記録されるように、classが顧客を表現するために使用されることを考慮します.
ここのすべてのことはよく見えますが、2実際にはすべてのことも確かによく、別のメンバー変数が戦局に参加するまで:
このとき既存のcopying関数はローカルコピー(partical copy):顧客のnameをコピーしたが、新しく追加したlastTransactionはコピーしなかった.ほとんどのコンパイラは、最高警告レベルでも文句を言わない.これはコンパイラが「自分で書いたcopying関数」に対する復讐行為です.copying関数を書くことを拒否した以上、コードが不完全であれば、教えてくれません.結論:classにメンバー変数を追加する場合は、copying関数を同時に変更する必要があります.calssのすべての構造関数と非標準形式のoperator=を変更する必要があります.忘れたら、コンパイラが注意することはできません.
統合が発生すると、このテーマの最も暗い潜在的な危機をもたらす可能性があります.検討:
PriorityCustomerのcopying関数は、PriorityCustomer内のすべてのものをコピーしているように見えますが、もう一度見てください.はい、PriorityCustomerによって宣言されたメンバー変数がコピーされますが、各PriorityCustomerには継承されたCustomerメンバー変数のコピー(コピー)が含まれていますが、メンバー変数はコピーされていません.PriorityCustomerのcopyコンストラクション関数は、実パラメータがbase classコンストラクション関数に渡されることを指定していません(つまり、メンバーの初期値列にCustomerが記載されていません).したがって、PriorityCustomerオブジェクトのCustomer成分は、実パラメータを持たないCustomerコンストラクション関数(defaultコンストラクション関数)によって初期化されます.そうしないとコンパイルできません.defaultコンストラクション関数は、nameとlastTransactionに対してデフォルトの初期化動作を実行します.
以上の事態はPriorityCustomerのcopy assignmentオペレータにわずかに異なる.base classのメンバー変数を変更しようとしたことがないので、メンバー変数は変更されません.
クラスのbase class部分を慎重にコピーする必要があります
注意:
Copying関数は、「オブジェクト内のすべてのメンバー変数」および「すべてのbase class部分」がコピーされていることを確認します.
自分のcopying関数を宣言すると、デフォルトの実装のいくつかの動作が好きではないことをコンパイラに伝えることを意味します.コンパイラは犯されたように、奇妙な方法で敬意を表します.実装コードがほとんど間違いを犯すと、教えてくれません.
コンパイラではなく手動でcopying関数を書き、外部からの呼び出しがログに記録されるように、classが顧客を表現するために使用されることを考慮します.
void lgoCall(const string& funcName);
class Customer {
public:
...
Customer(const Customer& rhs);
Customer& operator=(const Customer& rhs);
...
private:
string name;
};
Customer::Customer(const Customer& rhs):name(rhs.name)
{
logCall("Customer copy constructor");
}
Customer& Customer::operator=(const Customer& rhs)
{
logCall("Customer copy constructor");
name = rhs.name;
return *this;
}
ここのすべてのことはよく見えますが、2実際にはすべてのことも確かによく、別のメンバー変数が戦局に参加するまで:
class Data { ... };
class Customer {
public:
...
private:
string name;
Data lastTransaction;
};
このとき既存のcopying関数はローカルコピー(partical copy):顧客のnameをコピーしたが、新しく追加したlastTransactionはコピーしなかった.ほとんどのコンパイラは、最高警告レベルでも文句を言わない.これはコンパイラが「自分で書いたcopying関数」に対する復讐行為です.copying関数を書くことを拒否した以上、コードが不完全であれば、教えてくれません.結論:classにメンバー変数を追加する場合は、copying関数を同時に変更する必要があります.calssのすべての構造関数と非標準形式のoperator=を変更する必要があります.忘れたら、コンパイラが注意することはできません.
統合が発生すると、このテーマの最も暗い潜在的な危機をもたらす可能性があります.検討:
class PriorityCustomer:public Customer {
public:
...
PriorityCustomer(const PriorityCustomer& rhs);
PriorityCustomer& operator=(const PriorityCustomer& rhs);
...
private:
int priority;
}
PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs):priority(rhs.priority)
{
logCall("PriorityCustomer");
}
PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs)
{
logCall("PriorityCustomer");
priority = rhs.priority;
return *this;
}
PriorityCustomerのcopying関数は、PriorityCustomer内のすべてのものをコピーしているように見えますが、もう一度見てください.はい、PriorityCustomerによって宣言されたメンバー変数がコピーされますが、各PriorityCustomerには継承されたCustomerメンバー変数のコピー(コピー)が含まれていますが、メンバー変数はコピーされていません.PriorityCustomerのcopyコンストラクション関数は、実パラメータがbase classコンストラクション関数に渡されることを指定していません(つまり、メンバーの初期値列にCustomerが記載されていません).したがって、PriorityCustomerオブジェクトのCustomer成分は、実パラメータを持たないCustomerコンストラクション関数(defaultコンストラクション関数)によって初期化されます.そうしないとコンパイルできません.defaultコンストラクション関数は、nameとlastTransactionに対してデフォルトの初期化動作を実行します.
以上の事態はPriorityCustomerのcopy assignmentオペレータにわずかに異なる.base classのメンバー変数を変更しようとしたことがないので、メンバー変数は変更されません.
クラスのbase class部分を慎重にコピーする必要があります
PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs):Customer(rhs),priority(rhs.priority)// base class copy
{
logCall("PriorityCustomer");
};
PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs)
{
logCall("PriorityCustomer");
Customer::operator=(rhs); // base class
priority = rhs.priority;
return *this;
}
注意:
Copying関数は、「オブジェクト内のすべてのメンバー変数」および「すべてのbase class部分」がコピーされていることを確認します.