2011-08-01 85 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

相关问题