我正在创建一个自己的Qt c++类,它应该从ui->作为构造函数的输入参数引用QCustomPlot。
应该是这样的:
myPlots::myPlots(QObject *parent, QCustomPlot& _plot ) :
QObject(parent), plot(_plot)
{
}
我不想以编程方式创建情节区域,因为它在UI编辑中更整洁。我不希望使用指针作为参数,因为引用更安全,语法更干净。然而,我得到以下错误:
"错误:myPlots::myPlots(QObject*, QCustomPlot&)的参数2缺少默认参数"显式myPlots(QObject *parent=0, QCustomPlot&_plot);"
我尝试=0和=null作为默认参数,但只得到错误。这里发生了什么?
你的问题中的错误是因为带有默认值的参数必须在参数之后,没有默认值,这是c++的规则。
对于_plot
参数是否有默认值,这取决于plot
成员变量是如何声明的。如果它不是一个引用,您可以将_plot
参数改为对一个常量的引用,并将默认构造的QCustomPlot
对象作为默认值:
myPlots(QObject *parent = nullptr, const QCustomPlot& _plot = QCustomPlot(parent));
但是,这只在plot
成员不是引用时才有效。如果是引用,那么您可能应该有两个构造函数:一个接受QCustomPlot
引用,另一个没有:
myPlots(QObject *parent = nullptr);
myPlots(QCustomPlot& plot_, QObject *parent = nullptr);
第一个构造函数需要创建一个QCustomPlot
实例,该实例在myPlots
实例的生命周期内永远不会被销毁,并将其用于引用。
根据c++标准
在给定的函数声明中,a之后的每个形参带默认实参的形参应该有默认实参在此或之前的声明中提供的或应该是一个函数参数包。
和
引用必须初始化为指向一个有效的对象或函数。[注:特别地,空引用不能存在于良好定义的程序,因为只有这样才能创建这样的引用将其绑定到通过a间接获得的"对象"空指针,导致未定义行为。
如果您想使用默认参数(对于函数或模板),则无法指示跳过的参数,您只能在末尾保留一些参数。
因此,c++强制您为后面的任何参数提供默认值。
如果第二个构造函数没有好的默认值,那么使用多个构造函数或更改参数顺序。
如果你真的想给左值引用参数一个默认值(非const和非move),使用全局静态对象。
对于其他引用/非引用,只在这里构造对象是可以的。
不要试图使用可爱的技巧强迫c++接受非对象,如果你这样做,你真的值得未定义行为你得到。
静态对象示例:
struct myPlots {
explicit myPlots(QObject *parent = 0, QCustomPlot& _plot = standard_plot);
static QCustomPlot standard_plot;
}
重新排序示例:
struct myPlots {
explicit myPlots(QCustomPlot& _plot, QObject *parent = 0);
}
重载示例:
struct myPlots {
myPlots(QObject *parent, QCustomPlot& _plot);
explicit myPlots(QCustomPlot& _plot);
}
直接或间接地将引用设置为0或NULL都不是一个好主意。公平地说,直接设置它甚至可能无法工作,因为它将无法编译,其余的将具有未定义的行为。
然而,编译器试图帮助你如何使用构造函数:
myPlots::myPlots(QObject *parent, QCustomPlot&_plot):QObject(父)、图(_plot)
在设置父类的构造函数中,通常将父类作为带有默认空指针值的最后一个参数,或者只得到父类的重载版本。虽然这不是这里的主要问题。
问题是你试图使用一个没有有效对象的引用。您需要初始化对"有效"对象的引用。您可以通过代理对象将其初始化为空指针,这是引号。您可以将const引用设置为临时对象,但这会导致未定义的行为,因为临时对象会突然被销毁。
我个人建议重新考虑您的设计,并使用指针或值语义。参考文献一般来说是好的,但我不认为它在这种特殊情况下有什么好处。
所以,我个人会这样写:
头文件explicit myPlots(QCustomPlot _plot, QObject *parent = Q_NULLPTR);
或
explicit myPlots(QCustomPlot *_plot = 0, QObject *parent = Q_NULLPTR);
在你开始在评论中询问Q_NULLPTR
之前,它并不神奇。这是一颗隐藏的宝石,但它可以自由使用,因为维护人员说它不会破碎。在没有c++ 11或更高版本支持的情况下,它会简单地退回到0
,否则它将被定义为nullptr
,因此您的软件将同时使用两者。