2011-08-01 83 views
2

是否可以在C++中的另一個類的構造函數中初始化一個類的對象?我通常只會在main()中聲明對象,但我很想知道這是否可行並且是一個好習慣。 「新」和沒有「新」運營商的情況有什麼影響。它在哪裏被銷燬?是否有可能在C++中的另一個類的構造函數中聲明一個類的對象?

例如假設一個名稱空間和一個帶「新」運算符的示例

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++的書。用'new'分配簡單的整數是不值得的。 –

+2

你是一個正在恢復的Java程序員嗎? –

+0

沒有一個Java程序員問我這個問題,因爲我沒有使用這種類型的設計,我想我可能會問這堆棧溢出,因爲我不知道我自己。我是C和C++程序員。 – enthusiasticgeek

回答

2

關於您的實際問題,是的,這是非常好的做法(據聲明中B的構造函數去)。這將工作並正確地調用A的析構函數。

但是:關於代碼片斷您發佈,在A的構造函數分配兩個目標是不實踐。如果operator newh失敗,則w將被泄漏。如果在其構造函數中引發異常,則不會調用析構函數。因此,如果new int引發hw將不會被刪除。

+0

好點,沒想到那麼遠。難道他不能在第二次分配時放置try-catch,如果第二次分配失敗,如果第二次分配失敗,則刪除第一個整數(當然有一些額外的代碼)? –

+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我在一分鐘內想出了一個任意的例子。感謝您的建議並感謝您的回答。 – 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

相關問題