James Richmond
James Richmond

Reputation: 55

Destructor called immediately after constructor

I'm trying to create a Window class but for some reason a simple definition of a Window object is followed by calling it's destructor immediatly after.

The Window class' header has the following constructors and copy control defined:-

Window();
Window(int);
Window(const char* title);
Window(string title);
Window(const char* title, int x, int y, int width, int height);
Window(string title, int x, int y, int width, int height);
Window(const Window &window);
Window& operator=(const Window &window);
~Window();

The associated code for these functions is as follows:-

Window::Window()
{
  Window(default_title, default_width, default_height, default_xpos, default_ypos);
}

Window::Window(int)
:title_(default_title),
size_({ default_width, default_height }),
position_({ default_xpos, default_ypos })
{
  context_ = glutCreateWindow(title_.c_str());
  setposition(position_);
  setsize(size_);
  glutSetWindow(context_);
}

Window::Window(string title)
:Window(title, default_width, default_height, default_xpos, default_ypos)
{ }

Window::Window(const char* title)
{
  string t(title);
  Window(t, default_width, default_height, default_xpos, default_ypos);
}


Window::Window(const char* title, int x, int y, int width, int height)
{
  string t(title);
  Window(t, width, height, x, y);
}

Window::Window(string title, int x, int y, int width, int height)
:title_(title),
size_({ width, height }),
position_({ x, y })
{
  context_ = glutCreateWindow(title.c_str());
  refresh();
  setcallbacks();
  glutSetWindow(context_);
}

Window::Window(const Window &window)
:title_(window.title_),
size_(window.size_),
position_(window.position_)
{
  context_ = glutCreateWindow(title_.c_str());
  refresh();
  glutSetWindow(context_);
}

Window& Window::operator= (const Window &window)
{
  title_ = window.title_;
  size_ = window.size_;
  position_ = window.position_;
  context_ = window.context_;
  refresh();
  glutSetWindow(context_);
  return *this;
}

Window::~Window()
{
  glutDestroyWindow(context_);
}

None of the other functions used in the above code such as refresh() and setcallbacks() directly altar the class but instead call glut functions. If you think they're relevant I'll include them.

The problematic line is shown below, called as part of the main function:-

Window win("blah");

I've tried several configurations of this including the empty constructor, the full constructor and assignment but none seem to work. As far as I can tell, the constructor runs and initializes all the variables as expected then inexplicably calls the destructor when it advances to the next statement in the main function.

Upvotes: 0

Views: 2696

Answers (2)

Nelfeal
Nelfeal

Reputation: 13269

To understand why your code doesn't work as you want it to, you need to know how constructor calls work.

In your default constructor, for exemple, you call another constructor that will create a Window object. But this new object is restrained to the default constructor scope ! So when you leave this scope (when the default constructor call ends), the object is destroyed by calling its destructor.

You can observe this because in the following constructor, you create a glut window (context_) and set it :

Window(string title, int x, int y, int width, int height)

Then, in the destructor, you destroy this glut window. Notice that you only called the destructor of the temporary object restrained to the default constructor scope ! The original call to the default constructor still creates a Window (an empty one) that stays in another scope.

To solve this and do what you originally wanted to do, you need to use constructor delegation (C++11 only). You do it by calling another constructor in the constructor initialization list like that :

Window::Window(/* some arguments */)
    : Window(/* other arguments (other constructor) */) {
    // other stuff
}

Also notice that you can use default parameters. Exemple here :

Window(string title = default_title,
       int x = default_xpos, int y = default_ypos,
       int width = default_width, int height = default_height);

And I think that you swapped the coordinates with the dimensions in your calls.

Upvotes: 0

galop1n
galop1n

Reputation: 8824

It is because you cannot call a constructor like this :

Window::Window(const char* title, int x, int y, int width, int height)
{
  string t(title);
  Window(t, width, height, x, y); // this create a temporary Window then destroy it
}

Instead do this :

Window::Window(const char* title, int x, int y, int width, int height)
    : Window( string(t), width, height, x, y)
{}

Upvotes: 7

Related Questions