2011-08-01 15 views
2

C++の別のクラスのコンストラクタであるクラスのオブジェクトを初期化することはできますか?私は通常、メイン()内のオブジェクトのみを宣言しますが、これが可能かどうか、そして良い方法があるのか​​どうか不思議です。 「新規」の意味とは何か、「新しい」演算子がない場合です。それはどこで破壊されますか?C++の別のクラスのコンストラクタにあるクラスのオブジェクトを宣言することはできますか?

1つの名前空間と「新しい」演算子を使用する例を仮定すると、

class A{ 
private: 
protected: 
int *w, int *h; 
public: 
A(){ 
w = new int; 
h = new int; 
}; 
virtual int area (return ((*w)*(*h)) ;) 
virtual ~A() 
{ 
    delete w; 
    delete h; 
} 
} 

class B{ 
public: 
B() 
{ 
A a1; // This is usually in the main(); 
// Is this good practice 
//Where will the object be destroyed 
} 
virtual ~B(); 
} 
+5

C++については、1つまたは2つの書籍を読むことをお勧めします。単純な整数を 'new'で割り当てることは価値がありません。 –

+2

復旧中のJavaプログラマですか? –

+0

いいえ、1人のJavaプログラマが私にこの質問をしました。このタイプのデザインを使用していないので、私は自分自身がわからないので、スタックオーバーフローでこれを尋ねるかもしれないと思っていました。私はCとC++のプログラマーです。 – enthusiasticgeek

答えて

2

あなたの実際の質問について、はい、これは完全に良い練習(限り内部Bのコンストラクタを宣言しています行く)。これは正しく動作し、Aのデストラクタを適切に呼び出します。

は、しかし:コードについては、あなたがAのコンストラクタで2つのオブジェクトを割り当て、投稿ないお勧めしスニペット。 hoperator newが失敗すると、wがリークします。 Aのデストラクタは、コンストラクタ内で例外がスローされた場合には呼び出されません。したがって、に対してnew intがスローされた場合、wは削除されません。

+0

良い点は、それほど遠いとは思わなかった。彼が2番目の割り振りにtry-catchを置き、2番目が失敗した場合は最初の整数を削除できませんでしたか? –

+1

それはかなりきれいではありませんが、例外的に安全です。はい。スマートポインタを使用することは、たいていの場合、優れた解決策とみなされます。 – Damon

+0

http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.10では、[17.10]セクションの「スマートポインタ」の使用を推奨します。コンストラクタが例外をスローする可能性がある場合、リソースをどのように処理すればよいですか? – enthusiasticgeek

2

問題がありますか?コンストラクタはあなたの目的のための普通の関数なので、関数スコープの終わりに削除されるAのローカルオブジェクトa1を宣言するだけです。

クラスAはおそらく非常に危険に設計されています(コピー、割り当て、例外を考えてください)、おそらくAのメンバーにダイナミックストレージを割り当てる必要はありません。


更新:はここであなたの心に持っていたかもしれない何かの例です:

class Rectangle 
{ 
    unsigned int h, w; 
public: 
    Rectangle() : h(0), w(0) { } 
    Rectangle(unsigned int height, width) : h(height), w(width) { } 
    virtual ~Rectangle() { } 
    virtual unsigned int area() const { return h * w; } 
    virtual bool isSquare() const { return false; } 
}; 

class Square : public Rectangle 
{ 
public: 
    Square(unsigned int edge) : Rectangle(edge, edge) { } 

    // no need to override "area" 
    virtual bool isSquare() const { return true; } 
}; 
+0

ありがとうございましたKerrek 1分で任意の例を考え出しました。あなたの提案を感謝し、答えに感謝します。 – enthusiasticgeek

+0

@virgoptrex:問題ありません。興味のある場合は、派生クラスで基本クラスのコンストラクタを呼び出す方法の例を追加しました。 –

2

これは完全に問題ありません。実際には、コンストラクタで必要なものを作成するオブジェクトには適しています。デストラクタで適切に割り当てを解除して、メモリリークがないようにしてください。

「新しい」と「新しい」演算子がない場合の意味は何ですか。問題ではありません。それらがポインタでない場合(h & w)、クラスが作成されたときにデフォルトで作成されます。

private: 
    int w; 
    int h; 

public: 
    A() : w(0), h(0){ /* already done. */ }; 

あなたが永続化するオブジェクトを必要とする理由がない限り、あなたは新しい使用しないでください、それは可能性が高くなります:あなたはこのような初期化子リストでたい場合けれどもあなたは非ポインタオブジェクトを初期化することができますメモリリークや割り当てに失敗することがあります。どちらもうまくいく。

-w00te

+0

初期化リストの概念に注目するため+1。それらの詳細については、http://stackoverflow.com/questions/1598967/benefits-of-initialization-listsを参照してください。 – Hoons

関連する問題