Frustration in Qt: MyClass obj; makes my application refuse to show up. MyClass *obj = new MyClass; works fine.
-
To be honest, my title might be a little confusing.
I'm experimenting with Qt, making a desktop application that allows the user to "play" with a list of movies. Play as in add, edit or remove movies.
So I've made a Movie class of my own, for it to be used in conjuction with the other custom classes.
Here's movie:
@#ifndef MOVIE_H
#define MOVIE_H#include <QObject>
#include <QStringList>class Movie
{
int movieID;
QString movieTitle;
QString movieGenre;
QString movieDirector;
int movieDuration;
QStringList movieCast;
int movieYear;
int three_dim;public:
Movie();
~Movie();void setID(int given_ID); void setTitle(QString given_title); void setGenre(QString given_genre); void setDirector(QString given_director); void setDuration(int given_duration); void addCast(QString given_cast); void setYear(int given_year); bool is3D(); int getID(); QString getTitle();
};
#endif // MOVIE_H@
Please excuse the lack of some getters.
The constructor of Movie, Movie(), just sets all the variables for non-valid-for-my-program values. 0 for every int, "" for every QString.So I'm also making a Game class, which looks like this and is the "beef" of the application:
@#ifndef GAME_H
#define GAME_H#include <QWidget>
#include <QtGui>
#include <movie.h>
#include <theater.h>
#include <screening.h>class Game : public QWidget
{
private:
Q_OBJECT
int screen; //Defines what we display to the player
QVBoxLayout *layout; //Layout of the whole game widget
QList<Movie> movieList; //The list of the player's moviespublic:
explicit Game(QWidget *parent = 0);
~Game();void initialiseGame(); int getScreen(); //HELPERS void clearLayout(QLayout *local_layout); void setScreen(int num); //Sets our screen to a specific value void showScreen(); //According to what our screen is, we show the appropriate output and choices
signals:
int screenChanged(int newScreen); //Might help with bugfixingprivate slots:
void quit();
void newGame();
void editMovies();
void toMainMenu();
void screenBack();
void screenForward();public slots:
};
#endif // GAME_H
@The constructor of Game looks like this:
@Game::Game(QWidget *parent) :
QWidget(parent)
{
layout = new QVBoxLayout(this); //Layout initialised before setScreen() is called.
movieList = QList<Movie>(); //This should initialise our movieList to an empty one.
//movieList->clear(); //In case there's junk in it, we can always uncomment this line.Movie space_odyssey; //MARKER: Problem is here space_odyssey.setTitle("Space Odyssey"); movieList.append(space_odyssey); setScreen(1); //Game starts!
}@
You might expect this constructor to go through. Nope.
It won't allow the layout (which gets set-up through setScreen() and then shown in main() ) and, while goes through compilation, causes a "The program has unexpectedly finished." runtime.I've narrowed it down to the line
@Movie space_odyssey;@
as everything else goes through fine (tested through a lot of qWarning()s) and, when commented out, the program works fine.Anybody have any idea of what I am doing wrong? It's 3am and I have still not managed to have any [b]POSITIVE[/b] results.
Note that if you do @Movie *space_odyssey;@ or @Movie *space_odyssey = new Movie();@ the program continues fine. But this has a problem of being a needless pointer and also something that my QList is not made to work with.
If it matters, dears, my main looks like this:
@int main(int argc, char *argv[])
{
QApplication TheaterManager(argc, argv);MainWindow *window = new MainWindow; //Our main window //Notepad *notepad = new Notepad; Game *game = new Game(window); //The game itself, acts as a central widget //of our window. game.screen starts at 1. window->setCentralWidget(game); window->setMinimumSize(630,230); window->show(); return TheaterManager.exec();
}@
MainWindow is a currently completely plain QMainWindow subclass.
-
When you have
@
Movie space_odyssey; //MARKER: Problem is here
@space_odyssey is created on the stack. As soon as the Game constructor exits (4 lines later) space_odyssey is destroyed.
Using
@
Movie *space_odyssey = new Movie();
@
creates the object on the heap, and allows it to exist past the end of your destructor (although you should either make Game the parent of space_odyssey so that it cleans up after itself, or make the space_odyssey pointer a member variable so you can manually delete it in Game's destructor.It's not a "needless pointer." In fact, it's a very necessary pointer :)
-
What I do not understand is, why would a pointless stack object being created and being destroyed a few lines after affect the outcome of the program in the slightest?
Would that imply that the problem is in the deconstructor of my Movie class?
-
Ah, I believe I misunderstood your original question/problem. Sorry.
-
Turns out it actually was... my deconstructor consisted of Movie::~Movie(){ delete this;} which would obviously malfunction in case of a non-pointer object.
Thanks a lot, mlong.
And I'll be damned if I don't thank you for your swift reply.
-
No problem, glad that it led to the right solution after all!
Edit to add:
You would never use
@
delete this;
@in a destructor (or anywhere for that matter, typically.)
Calling delete on an object is actually what causes the destructor to be called.
-
So by doing it I was causing an infinite loop, no?
-
Perhaps, but it's at best an undefined (and definitely undesirable) behavior.
-
When you create a child class in a parent class and try to delete the child class in the class itself, you will most definitely get a segfault. It is the parents job to mop that up.