-3

so I'm at the point where I think I'm comfortable enough to start trying some frameworks/apis so I am thinking of learning the qt framework so I can start developing some simple gui applications,

anyway I noticed one strange thing in the qt MainWindow.cpp file

  MainWindow::MainWindow(QWidget *parent) :  
    QMainWindow(parent),  
    ui(new Ui::MainWindow)  
{  
    ui->setupUi(this);  
}

so I understand that ui is a pointer and we allocate a new MainWindow object to that pointer

but when I do pretty much the same thing with my own code everytime the program crashes

#include <iostream>

using namespace std;


    class Sample{

     public:
         Sample* ss; [c++]
         string text = "hey ya";
         explicit Sample()
         :ss(new Sample){

           cout << "hi" << endl; // doesn't print hi?
         }

         void print(){
            cout << ss->text << endl;
         }

         ~Sample(){

           delete ss;
         }
    };

    int main()
    {
        cout << "Hello world!" << endl;
        Sample s;
        return 0;
    }

at first I thought the crash was because of an infinite recursion each constructor will keep calling a new Sample

but if this was the case shouldn't hey be printed to the console?

also how come this code works in qt yet mine won't work,I mean it's pretty much doing the same thing,

note that in the qt MainWindow header the constructor is mark explicit if that makes any difference,I tried marking my constructor in my Sample class as explicit but still crashes

thanks

dtech
  • 47,916
  • 17
  • 112
  • 190
  • 5
    Sounds like a good time to open your debugger, and look at the callstack. You'll learn all about constructors if you do that; and why you didn't get "hi" printed – UKMonkey Mar 07 '18 at 17:00
  • 2
    the two codes that you sample do not resemble at all – eyllanesc Mar 07 '18 at 17:03
  • where did you find that Qt example? – default Mar 07 '18 at 17:04
  • Qt does not call the MainWindow constructor of your class but rather the MainWindow class that was created by the moc (as you can see by the Ui namespace) – Christian G Mar 07 '18 at 17:04
  • `Ui::MainWindow` is different to `MainWindow`!!!! – eyllanesc Mar 07 '18 at 17:05
  • 1
    @eyllanesc There is no inheritance, those are two different MainWindow classes. – Christian G Mar 07 '18 at 17:06
  • @eyllanesc The point I was trying to make was that the inheritance is irrelevant to the fact that thhis does not stackoverflow - even if MainWindow had QMainWindow simply as a member instead of inheriting – Christian G Mar 07 '18 at 17:12
  • Possible duplicate of [A newbie question in Qt](https://stackoverflow.com/questions/4847110/a-newbie-question-in-qt) – Mohammad Kanan Mar 07 '18 at 17:45
  • Unrelated: If you have not already, read [What is The Rule of Three?](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) – user4581301 Mar 07 '18 at 17:48
  • **Also** a duplicate of [Is MainWindow initialized with itself in qt5](https://stackoverflow.com/questions/28016303/is-mainwindow-initialized-with-itself-in-qt5) – Mohammad Kanan Mar 07 '18 at 17:51

2 Answers2

4

but when I do pretty much the same thing with my own code everytime the program crashes

It is not "pretty much the same" - in appearance - somewhat, yet looks can be deceiving when you don't pay attention to the details, but functionally it is far from it.

Your code is a class that infinitely creates itself, each new instance of the class creates another instance, that instance creates another and so on until you hit some (runtime, operating system or hardware) limit and your application crashes. Your code never reaches the "hi" part for even the first object created.

This has nothing to do with the Qt example code. In that code, the class doesn't create a new instance of itself in the constructor. It creates a different class that was generated from a UI form. Although the class name is the same, it is not the same class, as it exists in the Ui namespace. The classes are named the same because they are complimentary, they don't have to be but that's what Qt does when it generates code for you. And it makes sense, since it makes it clear which widget class corresponds to which form class.

MainWindow and Ui::MainWindow are not the same classes, which is why it makes sense and actually works.

Note that C++ won't even let you have an instance of the class inside the same class, neither directly nor through indirect inheritance or aggregation, that's a default no-no as the infinite recursion is obvious to the compiler, however deeply it may be nested. But having a pointer is OK, because the pointer is basically just a reference to another object which is OK and frequently used, and you must assume the responsibility to make sure that even if it creates another object of the same type rather than simply reference a pre-existing object, you limit that behavior so that it doesn't run into infinite recursion.

struct RTest {
    RTest(int & d) {
      qDebug() << "hi" << d;
      t = d++ < 10 ? new RTest(d) : nullptr;
    }
    RTest * t;
};

In this case the recursion is limited to a depth of 10. Note that if you do the pointer initialization in the initializer list, you won't get hi from 0 to 10, but only hi 11s as the body of the constructor of the first object will not be reached until the recursion is finished, which is why you never get your code to your hi.

dtech
  • 47,916
  • 17
  • 112
  • 190
1

but if this was the case shouldn't hey be printed to the console?

Nope. When you construct a class the class member initialization list happens first. That means

ss(new Sample)

happens before you even enter the body of the constructor. Since that line creates a new Sample you initialize that Sample which creates another new Sample and this process will happen forever until the OS stops you or the process crashes

NathanOliver
  • 171,901
  • 28
  • 288
  • 402