2

Is it possible to initialize objects of one class in the constructor of another class in c++? I usually will declare objects only in the main(), however I am curious to know if this is possible and a good practice. What are the implications with "new" and a case without "new" operator. Where does it get destroyed?

e.g. Assuming one namespace and an example with "new" operator

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();
}
enthusiasticgeek
  • 2,640
  • 46
  • 53
  • 5
    You may want to read a book or two about C++. Allocating simple integers with `new` is not worth it. – Alexandre C. Aug 01 '11 at 16:43
  • 2
    Are you a recovering Java programmer? – Kerrek SB Aug 01 '11 at 16:45
  • Nope one Java programmer asked me this question and since I haven't used this type of design I thought I may ask this on Stack Overflow as I wasn't sure myself. I am C and C++ programmer. – enthusiasticgeek Aug 01 '11 at 16:48
  • Thanks for that valuable recommendation Alexandre. +1 points for that. I needed some arbitrary example to post a question but didn't consider dynamic allocation of simple data types would be bad. – enthusiasticgeek Aug 01 '11 at 16:55

3 Answers3

2

What's the problem? The constructor is just an ordinary function for your purposes, so all you are doing is declaring a local object a1 of type A which gets deleted at the end of the function scope.

Note that your class A is probably very dangerously designed (think of copying, assignment and exceptions), and it's probably entirely unnecessary to allocate dynamic storage for A's members.


Update: Here's an example of something you might have had in mind:

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; }
};
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Thanks Kerrek I came up with an arbitrary example in a minute's time. appreciate your suggestions and thanks for answer. – enthusiasticgeek Aug 01 '11 at 16:53
  • @virgoptrex: No problem. I've added an example of how to call the base class constructor in a derived class, in case that's of interest. – Kerrek SB Aug 01 '11 at 16:57
2

About your actual question, yes this is perfectly good practice (as far as declaring A inside B's constructor goes). This will work and properly call A's destructor.

However: About the code snippet you posted, allocating two objects in A's constructor is not good practice. If operator new for h fails, then w will be leaked. A's destructor will not be called if an exception is thrown inside its constructor. Thus, w will not be deleted if new int throws for h.

Damon
  • 67,688
  • 20
  • 135
  • 185
  • Good point, didn't think that far. Couldn't he place a try-catch on the second allocation and delete the first integer if the second failed though if he wished (with some added code of course)? – John Humphreys Aug 01 '11 at 16:58
  • 1
    That would not be super pretty, but it would be exception safe, yes. Using a smart pointer will probably be regarded as the superior solution by most people. – Damon Aug 01 '11 at 17:00
  • The http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.10 recommends using "smart-pointer" in the section [17.10] How should I handle resources if my constructors may throw exceptions? – enthusiasticgeek Aug 01 '11 at 17:03
  • 1
    @virgoptrex: You shouldn't handle resources unless you are specifically writing a class whose sole purpose is handling that resource. Make sure that class handles the resource properly(e.g. it follows [the rule of 3](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three)), then you can use that resource through that class, and you don't have to worry about exceptions. The most common resource handling classes that you will ever need have already been written and are provided in the standard library, so you may never even have to write one. – Benjamin Lindley Aug 01 '11 at 17:13
  • @Benjamin, Thats very helpful. I'll need to be more familiar with C++ Standard library. – enthusiasticgeek Aug 01 '11 at 17:43
2

That's perfectly alright - in fact, it's good for an object do create the things it requires in its constructor. You properly deallocated them in the destructor so you have no memory leak.

Also note that "What are the implications with "new" and a case without "new" operator." isn't an issue. If they weren't pointers (h&w) then they would be constructed by default when the class was created. You can initialize non-pointer objects though if you'd like with an initializer list like this:

private: 
    int w;
    int h;

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

You shouldn't use new unless you have a reason to need the objects to persist, it makes it more likely that you'll have a memory leak or allocation failure. Both work fine though.

-w00te

John Humphreys
  • 37,047
  • 37
  • 155
  • 255
  • +1 for noting the concept of Initialization Lists. See http://stackoverflow.com/questions/1598967/benefits-of-initialization-lists for more about them. – Rob Marrowstone Aug 01 '11 at 16:58