C++:コピーコンストラクタ:利用setterかまたはアクセス会員varsす。
-
18-09-2019 - |
質問
私は簡単なコンテナクラスのコピーコンストラクタです。
なご使用をお勧めしsetterか、セッター、またはアクセスアプリケーションはメンバ変数を直接?
public Container
{
public:
Container() {}
Container(const Container& cont) //option 1
{
SetMyString(cont.GetMyString());
}
//OR
Container(const Container& cont) //option 2
{
m_str1 = cont.m_str1;
}
public string GetMyString() { return m_str1;}
public void SetMyString(string str) { m_str1 = str;}
private:
string m_str1;
}
- 例では、すべてのコードはインラインで実際にコードがインラインのコードです。
Update(29月09):
これらの答えは、いつもこの欠点ではこの質問:
これは簡単なり、逆に例題を用いsetterか/セvs変数
初期化リストや民間のバリデータの機能んの質問です。った場合にはデザインのコードを維持しやすくなると拡大します。
一名に焦点を合わせて文字列でこの例では、しかし、あくまで目安ですが、例えば、想像で異なるオブジェクトです。
いつ。それにしても、なぜプログラミングにPDP-11
解決
あなたは例えば、文字列が返される方法を予想してください。ホワイトスペースはヌルなど、チェックし、トリミング?答えはイエスである場合SetMyString()と同じ、あなたは無数の場所で、あなたのコードを変更しますが、単にそれらのgetterメソッドとsetterメソッドを変更する必要はありませんので、アクセス方法がオフに優れています。
他のヒント
編集: 答えは、編集中の質問:)
これは簡単な例を出したり、逆に 議論をsetterか/vsセッター 変数
とした場合の変数にする必要がないものの検証、追加工後性を高めることが考えられますが使用ポッドです。から StroustrupのFAQ:
をもってクラスを提クリーン 簡単なインターフェース、ユーザー 隠その表現 保存 そのユーザーからも約 この表現。の場合 表現がなされているため と言うので、ユーザーできる 変更データに該会員のう -そのようなものと考えることができるクラスとして "無地の古いデータ構造"
短いものは、JAVA.なんか書平setterか/セッターなどが露出を変数にして自分自身を直視するためです。
初期化リストや民間のバリデータの機能にはいろいろな目的があ この質問です。った どちらかがデザインのコード 維持しやすくなると拡大します。
の場合はコピーを別のオブジェクトの変数は、そのソースオブジェクトのあるべき有効な状態です。どうして病気のソースオブジェクト形成されたのでしょうか。!なコンストラクタを検証?とは思わない正会員機能を担うの維持に不変なクラスを検証。ださを検証する"有効"のオブジェクトをコピーコンストラクタ?
いつ。それにしても、なぜプログラミングにPDP-11
これは、最もエレガントなスタイルはC++で最も優雅なコードは最高の性能特性ます。
すべ initializer list
.にコード m_str1
デフォルトの構築 その 割り当て新しい値とします。にコードされる課題が考えられようになります:
class Container
{
public:
Container() {}
Container(const Container& cont) : m_str1(cont.m_str1)
{ }
string GetMyString() { return m_str1;}
void SetMyString(string str) { m_str1 = str;}
private:
string m_str1;
};
@cbrulakんIMOの検証 cont.m_str1
の copy constructor
.What I do、検証も constructors
.検証 copy constructor
を意味しています複製、虐待形成のオブジェクトは、例えば:
Container(const string& str) : m_str1(str)
{
if(!valid(m_str1)) // valid() is a function to check your input
{
// throw an exception!
}
}
あなたは、初期化子リストを使用する必要があり、その後、質問はのように、無意味になります:
Container(const Container& rhs)
: m_str1(rhs.m_str1)
{}
すべてのメンバー初期化子リストについての説明マシュー・ウィルソンの不完全なC ++ のには大きなセクションがありますし、どのようにあなたについてあなたのコードをより安全にするためにCONSTおよび/または参照との組み合わせでそれらを使用することができます。
編集:検証とCONSTを示す例:
class Container
{
public:
Container(const string& str)
: m_str1(validate_string(str))
{}
private:
static const string& validate_string(const string& str)
{
if(str.empty())
{
throw runtime_error("invalid argument");
}
return str;
}
private:
const string m_str1;
};
それはあなたが同様に単なる文字列を公開する可能性があるとして行われるので、絶対に何も達成されていません(ご希望の場合は、アクセサとミューテータ、)あなたのゲッターとセッター(入力または出力の無資格で)今書かれているとおりこれます。
実際のコードが実際に文字列を修飾した場合、チャンスは何を扱っていることで、すべての文字列が正しくないことをかなり良いです - 代わりに、それは文字列のようにたくさん見えるだけで何かです。実数型のみビット列のようなものであるとき、何が本当にこのケースでやっていることは、文字列をさらすの並べ替えを型システムを悪用しています。その後、実数型は、実際の文字列と比較しているものは何でも制限が施行しようとするセッターを提供しています。
あなたがその方向から見た場合、、答えはかなり明白になり:文字列ではなく、他のいくつかの(より制限)タイプのような文字列を作用させるためのセッターと、あなたが代わりにやるべきことは、実際に定義されますあなたが本当にしたいタイプのクラス。正しくそのクラスを定義した、あなたはそれのインスタンスを公開します。それはそれを文字列として開始値を代入するのが妥当です(ここではケースのように思わとして)場合、そのクラスは、引数として文字列を取り代入演算子を含める必要があります。 (が、としても、ここでの場合のようです)場合、それはまた、結果として文字列を生成キャスト演算子を含めることができ、いくつかの状況下では、文字列にその型を変換するのが合理的です。
これは、周囲のクラスのセッターとゲッターを使用して上の実改善を与えます。あなたは、周囲のクラスのものを入れたときにまず第一に、それはセッターが強制することになったものは何でもの施行を失って、ゲッター/セッターを回避するために、そのクラス内のコードのために簡単です。第二に、それは通常の見える表記を維持しています。あなたが読み単なる醜いと難しいコードを書くためにゲッターとセッターの力を使用します。
あなたのような何かを置き換えることができますので、演算子オーバーロードを使用しているC ++における文字列クラスの主な強みの一つます。
strcpy(strcat(filename, ".ext"));
ます。
と
filename += ".ext";
ます。
読みやすさを向上させます。しかし、その文字列がゲッターとセッターを通過する私たちを強制的にクラスの一部である場合に何が起こるか見てます。
some_object.setfilename(some_object.getfilename()+".ext");
ます。
どちらかといえば、Cコードは、実際にはより読みやすいこの混乱を超えています。
この:一方で、我々は右の仕事をする場合は=演算子文字列演算子を定義するクラスのパブリック・オブジェクトに、何が起こるかを考えます
some_object.filename += ".ext";
ます。
それがあるべきと同じように、ニース、シンプルで読みやすいです。私たちは、文字列について何かを強制する必要がある場合は、より良いまだ、我々はそれだけで小さなクラスを調べることができ、私たちは本当にだけに1つまたは2つの特定の、よく知られた場所(そのクラスの演算子=、おそらくctorのか、2)を見ていますそれは常に強制だということを知っている - 私たちは仕事をしようとするセッターを使用しているときとは全く別の話を。
。コストと利益が何であるかを自問します。
コスト:高い実行時のオーバーヘッド。 ctorsで仮想関数を呼び出すことは悪い考えですが、セッターとゲッターは仮想ではないようです。
メリット:セッター/ゲッターは複雑な何かをする場合は、コードを繰り返していません。それは直感的に何かをしている場合、あなたはそれを行うには忘れていない。
費用/便益比は、異なるクラスごとに異なります。あなたはその比率を確認したら、あなたの判断を使用します。不変クラスについては、もちろん、あなたがセッターを持っていない、と(誰がそれらを取り付け直し/変更することはできないとして、constのメンバーとの言及は、公開することができたように)あなたはゲッターを必要としません。
ある銀の弾丸としての書き方のコピーコンストラクタです。の場合のみ会員に提供するコピーを生成するコンストラクタ インスタンスがない状態(または少なくとも表示されません)を初期化リストにあふれています。
その他ょっとおもいます。
struct alpha { beta* m_beta; alpha() : m_beta(new beta()) {} ~alpha() { delete m_beta; } alpha(const alpha& a) { // need to copy? or do you have a shared state? copy on write? m_beta = new beta(*a.m_beta); // wrong m_beta = a.m_beta; }
ご注意いただくことができて、潜在segfault用 smart_ptr
ができて楽しいデバッグに伴うございます。
もちろんでもfunnier.
- メンバーが作成されます。
new beta(a.beta)
は 間違った 場合には何らかの導入多型.
...ネジの その他 くことを常に考えて書きコピーコンストラクタです。
なぜ必要なものsetterか、セッターは全くないのでしょうか。
シンプルです:)などの保全不変量につ保証クラスするなど、"MyStringいつもの番号の文字の".
が実施されることになればとして、オブジェクトが常に有効な状態でmemberwiseコピーできるもののコピーをせずにその恐れの大切保証致しかねます。なので検証済みの状態を通してもの状態にバリデーションを実施します。
としてアラーク氏は、ベストが使用初期化リスト。
プロ(1):
他の理由に使用setterか/セッターな実装に依存します。ことになる不思議なアイデアをコピー CTorが変化するなどの実施の詳細のほとんど常に調整する必要がありCDAます。
プロ(2):
を証明する私の間違いを生成できます不変量に依存するインスタンス自体又はその他の外部要因です。(非常contrieved)例:"多数の場合はインスタンスであっても、文字列の長さでも、そうでない場合は、半端ないです。" その場合は、コピー CTorい投げや調整などの文字列になります。この場合も使用getter/setterか-でも、それだけではありませんのcas.なんかる一般規則から奇妙.
私は、データにアクセスするために、外側のクラスのためのインタフェースを使用して好みます。あなたはクラスの範囲内だとコピーされた値の内部状態を再現したい場合しかし、私は直接データメンバーで行くと思います。
ゲッターがインライン化されていない場合、あなたはおそらく、いくつかの関数呼び出しを救うことは言うまでもありません。
virtual
ない、何のプラスにもマイナスには、彼らにWRTの直接メンバー・アクセスを使用してありません - それだけでスタイルの面で私に間抜けに見えませんが、、大したいずれかの方法
は、はそこにのオーバーヘッドである...しかし、あなたがそれらを呼び出したい行うと、それにもかかわらず、それは彼らが、サブクラスでオーバーライドしているだけの場合には、正確です - !)
多くの設計の質問のために働くの簡単なテストがあり、この1つが含ま:。副作用を追加し、壊すものを参照してください。
と仮定セッターが値を代入するだけでなく、監査レコードを書き込み、メッセージをログに記録したり、イベントを発生させないだけ。オブジェクトをコピーするときに、これはすべてのプロパティのために起こりますか?おそらくない - ので、コンストラクタでセッターを呼び出すと(セッターが実際にちょうど割り当てている場合でも)論理的に間違っている。
。が同意するその他のポスターが多くのエントリレベルのC++"さんの"お試料を入れる側に回答のご質問は直接:
実際、私が多くなすべての会員の分野の公的、そして移動していく必要があります。
現在、私が初めて導入することになっていることを明らかにすることは必ずしもおすすめの練習に多くの実務者がabhorこったね"と言っていただけるあらゆる分野はgetter/setterか.
も参考になり嬉しいです。だが実際にこれだけではないが必要です。当たり前の原因となり痛時以降の変更を行った分野におかれては、ゲッターは、時にそれは分かりや利用クラスは、この設定または取得の分野で保護されたからプライベートをしていきたいと思っています。
YMMV
RF
- お電話の分野を"変数"に"-Iをご利用の時期だけにローカル変数内の関数/メソッド