Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 导致崩溃的递归构造函数?_C++_Qt_User Interface - Fatal编程技术网

C++ 导致崩溃的递归构造函数?

C++ 导致崩溃的递归构造函数?,c++,qt,user-interface,C++,Qt,User Interface,因此,我认为我可以开始尝试一些框架/API,因此我想学习qt框架,以便开始开发一些简单的gui应用程序 无论如何,我注意到qt MainWindow.cpp文件中有一个奇怪的东西 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } 所以我理解ui是一个指针,我们为该指针分配一个

因此,我认为我可以开始尝试一些框架/API,因此我想学习qt框架,以便开始开发一些简单的gui应用程序

无论如何,我注意到qt MainWindow.cpp文件中有一个奇怪的东西

  MainWindow::MainWindow(QWidget *parent) :  
    QMainWindow(parent),  
    ui(new Ui::MainWindow)  
{  
    ui->setupUi(this);  
}
所以我理解ui是一个指针,我们为该指针分配一个新的MainWindow对象

但是,每当程序崩溃时,我都会对自己的代码执行几乎相同的操作

#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;
    }
#包括
使用名称空间std;
类样本{
公众:
示例*ss;[c++]
string text=“你好”;
显式样本()
:ss(新样本){
库特
但是如果是这样的话,他们不应该被打印到控制台上吗

不。当你构造一个类时,类成员初始化列表首先发生。这意味着

ss(new Sample)
在您进入构造函数主体之前发生。由于该行创建了一个新的
Sample
,您将初始化该
Sample
,从而创建另一个新的
Sample
,此过程将永远发生,直到操作系统停止您或进程崩溃

但当我每次都用自己的代码做几乎相同的事情时 程序崩溃了

#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;
    }
它在外观上并不“几乎相同”,但如果你不注意细节,外观可能会有欺骗性,但从功能上来说,它与此相去甚远

您的代码是一个无限创建自身的类,该类的每个新实例创建另一个实例,该实例创建另一个实例,依此类推,直到您达到某个(运行时、操作系统或硬件)限制,应用程序崩溃。即使创建的第一个对象,您的代码也永远不会达到“hi”部分

这与Qt示例代码无关。在该代码中,类不会在构造函数中创建自身的新实例。它会创建一个从UI表单生成的不同类。虽然类名相同,但它不是同一个类,因为它存在于
UI
命名空间中。这些类被命名为同样,因为它们是互补的,所以它们不必是互补的,但这就是Qt为您生成代码时所做的。这是有意义的,因为它清楚地表明了哪个小部件类对应于哪个表单类

MainWindow
Ui::MainWindow
不同的类,这就是为什么它是有意义的并且实际上是有效的

注意,C++甚至不允许你在同一个类中有一个类的实例,既不直接也不间接继承或聚合,默认为“否”,因为无限递归对于编译器是显而易见的,但是它可能是嵌套的,但是指针是可以的,因为指针基本上只是对ANO的引用。这是一个正常且经常使用的对象,您必须负责确保即使它创建了另一个相同类型的对象,而不是简单地引用一个预先存在的对象,您也会限制该行为,以便它不会陷入无限递归

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

qDebug()听起来是打开调试器并查看调用堆栈的好时机。如果这样做,您将了解有关构造函数的所有信息;以及为什么没有得到“hi”打印出您所采样的两个代码一点也不相似,您在哪里找到了Qt示例?Qt不调用类的MainWindow构造函数,而是调用由moc创建的MainWindow类(如Ui命名空间所示)@eyllanesc没有继承,这是两个不同的MainWindow类。