Деструктор вызывается сразу после конструктора

0

Я пытаюсь создать класс Window, но по какой-то причине простое определение объекта Window сопровождается немедленным вызовом его деструктора.

Заголовок "Класс окна" имеет следующие конструкторы и управление копированием:

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();

Соответствующий код для этих функций выглядит следующим образом:

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_);
}

Ни одна из других функций, использованных в вышеприведенном коде, таких как refresh() и setcallbacks(), не имеет прямого доступа к классу, а вместо этого вызывает функции переполнения. Если вы считаете, что они актуальны, я их включу.

Проблематичная линия показана ниже, называемая частью основной функции: -

Window win("blah");

Я пробовал несколько конфигураций, включая пустой конструктор, полный конструктор и назначение, но ни один из них не работает. Насколько я могу судить, конструктор запускает и инициализирует все переменные, как ожидалось, а затем необъяснимо вызывает деструктор, когда он переходит к следующему выражению в основной функции.

  • 0
    Хорошо, если вы назвали Window win("blah"); без использования его в реальной области действия следующий шаг - то, что деструктор вызывается как ожидалось.
Теги:
c++11
constructor
destructor

2 ответа

6
Лучший ответ

Это потому, что вы не можете вызвать конструктор следующим образом:

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
}

Вместо этого сделайте следующее:

Window::Window(const char* title, int x, int y, int width, int height)
    : Window( string(t), width, height, x, y)
{}
  • 2
    Однако следует отметить, что это возможно только с C ++ 11 и выше.
  • 1
    Да, но я проверил сначала, и вопрос помечен c ++ 11, так что ...
Показать ещё 3 комментария
0

Чтобы понять, почему ваш код не работает так, как вы хотите, вам нужно знать, как работают вызовы конструктора.

Например, в вашем конструкторе по умолчанию вы вызываете другой конструктор, который будет создавать объект Window. Но этот новый объект сдерживается конструкцией по умолчанию! Поэтому, когда вы покидаете эту область (когда заканчивается вызов конструктора по умолчанию), объект уничтожается, вызывая его деструктор.

Вы можете наблюдать это, потому что в следующем конструкторе вы создаете окно context_ (context_) и устанавливаете его:

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

Затем, в деструкторе, вы уничтожаете это окно с избытком. Обратите внимание, что вы только вызвали деструктор временного объекта, сдержанного к области конструктора по умолчанию! Первоначальный вызов конструктора по умолчанию все еще создает Window (пустое), которое остается в другой области.

Чтобы решить эту задачу и выполнить то, что вы изначально хотели сделать, вам нужно использовать делегирование конструктора (только С++ 11). Вы делаете это, вызывая другой конструктор в списке инициализации конструктора следующим образом:

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

Также обратите внимание, что вы можете использовать параметры по умолчанию. Пример здесь:

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

И я думаю, что вы меняли местами координаты с размерами в ваших звонках.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню