简体   繁体   English

将引用传递给构造函数,默认参数

[英]Passing reference to constructor, default argument

I'm creating an own Qt C+ class that is supposed to take a reference to a QCustomPlot from the ui-> as input argument to the constructor. 我正在创建一个自己的Qt C +类,该类应该从ui->中引用QCustomPlot作为构造函数的输入参数。

It should look like this: 它看起来应该像这样:

myPlots::myPlots(QObject *parent, QCustomPlot& _plot ) :
    QObject(parent), plot(_plot)
{


}

I dont want to create the plot area programmatically as it's neater do to it in the UI edit. 我不想以编程方式创建绘图区,因为它在UI编辑器中比较整洁。 And don't wish to use a pointer as argument as references are safer and more syntax clean as I understand. 而且我不希望将指针用作参数,因为据我所知,引用更安全,语法更简洁。 However I get the following error: 但是我收到以下错误:

"error: default argument missing for parameter 2 of 'myPlots::myPlots(QObject*, QCustomPlot&)' explicit myPlots(QObject *parent=0, QCustomPlot& _plot);" “错误:'myPlots :: myPlots(QObject *,QCustomPlot&)'显式myPlots(QObject * parent = 0,QCustomPlot&_plot)的参数2缺少默认参数。“

I tried =0 and =null as default argument but only got errors. 我尝试将= 0和= null用作默认参数,但只有错误。 What is happening here? 这是怎么回事

The error in your question is because arguments with default values must be after arguments without default values, those are the rules of C++. 您问题中的错误是因为具有默认值的参数必须没有默认值的参数之后 ,这些是C ++的规则。


As for having the _plot argument having a default value, it kind of depends on how the plot member variable is declared. 至于使_plot参数具有默认值,则取决于如何声明plot成员变量。 If it's not a reference, you can make the _plot argument a reference to a constant instead and have a default-constructed QCustomPlot object as default value: 如果不是引用,则可以使_plot参数代替对常量的引用,并使用默认构造的QCustomPlot对象作为默认值:

myPlots(QObject *parent = nullptr, const QCustomPlot& _plot = QCustomPlot(parent));

However, this only works if the plot member is not a reference. 但是,这仅在plot成员不是参考的情况下有效。 If it is a reference, then you should probably have two constructors: One taking a QCustomPlot reference, and one without: 如果它一个引用,则您可能应该有两个构造函数:一个带有QCustomPlot引用,另一个没有:

myPlots(QObject *parent = nullptr);
myPlots(QCustomPlot& plot_, QObject *parent = nullptr);

The first constructor needs to create a QCustomPlot instance that is never destroyed during the lifetime of the myPlots instance being constructed, and use that for the reference. 第一个构造函数需要创建一个QCustomPlot实例,该实例在所构造的myPlots实例的生存期内不会被破坏,并将其用作参考。

If you want to use default arguments (for functions or templates), there's no way to indicate a skipped argument, you can only leave some off at the end. 如果要使用默认参数(用于函数或模板),则无法指示跳过的参数,只能在最后保留一些参数。
Therefore, C++ forces you to provide defaults for any argument following one having such. 因此,C ++会强制您为具有此参数的任何参数提供默认值。
If there's no good default for the second but for the first, use multiple constructors or change the arguments ordering. 如果第二个都没有好的默认值,但第一个没有好的默认值,请使用多个构造函数或更改参数顺序。

If you really want to give a default for a l-value reference argument (non-const and non-move), use a global static object. 如果您确实想为左值引用参数(非常量和非移动)提供默认值,请使用全局静态对象。
For other references / non-references, constructing an object just there is ok. 对于其他引用/非引用,只需构建一个对象即可。

Do not try to force C++ to accept a non-object using cute tricks, if you do you really deserve the Undefined Behavior you get. 如果确实值得得到未定义的行为,请不要尝试使用可爱的技巧强迫C ++接受非对象。

Example for static object: 静态对象的示例:

struct myPlots {
    explicit myPlots(QObject *parent = 0, QCustomPlot& _plot = standard_plot);
    static QCustomPlot standard_plot;
}

Example for reordering: 重新排序示例:

struct myPlots {
    explicit myPlots(QCustomPlot& _plot, QObject *parent = 0);
}

Example for overloads: 重载示例:

struct myPlots {
    myPlots(QObject *parent, QCustomPlot& _plot);
    explicit myPlots(QCustomPlot& _plot);
}

According to the C++ Standard 根据C ++标准

In a given function declaration, each parameter subsequent to a parameter with a default argument shall have a default argument supplied in this or a previous declaration or shall be a function parameter pack. 在给定的函数声明中,带有默认参数的参数之后的每个参数都应具有此或先前声明中提供的默认参数,或者应为函数参数包。

and

A reference shall be initialized to refer to a valid object or function. 引用应初始化为引用有效的对象或函数。 [ Note: in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the “object” obtained by indirection through a null pointer, which causes undefined behavior. [注意:尤其是,空引用不能存在于定义良好的程序中,因为创建此类引用的唯一方法是将其绑定到通过空指针间接获得的“对象”,这将导致未定义的行为。

It is not a good idea to set a reference to zero or NULL directly or indirectly. 直接或间接将引用设置为零或NULL并不是一个好主意。 To be fair, setting it directly will probably not even work because it will fail to compile, and the rest will have undefined behavior. 公平地说,直接设置它可能甚至无法工作,因为它将无法编译,而其余的将具有未定义的行为。

However, the compiler is trying to help you how to use the constructor: 但是,编译器试图帮助您如何使用构造函数:

myPlots::myPlots(QObject *parent, QCustomPlot& _plot ) : QObject(parent), plot(_plot) myPlots :: myPlots(QObject * parent,QCustomPlot&_plot):QObject(parent),plot(_plot)

In constructors setting parents, you usually leave the parent as the last argument with default null pointer value, or you get an overloaded version with the parent only. 在设置父级的构造函数中,通常将父级保留为具有默认null指针值的最后一个参数,或者仅使用父级获得重载版本。 Although that is not the main issue in here. 尽管这不是这里的主要问题。

The issue is that you are trying to use a reference without a valid object. 问题是您正在尝试使用没有有效对象的引用。 You need to initialize references to "valid" objects. 您需要初始化对“有效”对象的引用。 You could initialize it to null pointer through a proxy object, this the quote. 您可以通过代理对象(引号)将其初始化为空指针。 You could set a const reference to a temporary object, but that would have undefined behavior as the temporary get destructed abruptly. 您可以设置对临时对象的const引用,但是由于临时破坏会突然破坏临时对象,因此它具有未定义的行为。

I would personaly suggest to reconsider your design and use pointer or value semantics. 我个人建议重新考虑您的设计并使用指针或值语义。 References are good in general, but I do not see the gain of it in this particular case. 一般而言,引用是好的,但是在这种特殊情况下,我看不到它的好处。

So, I would personally write something like this: 所以,我个人会这样写:

header file 头文件

explicit myPlots(QCustomPlot _plot, QObject *parent = Q_NULLPTR);

or 要么

explicit myPlots(QCustomPlot *_plot = 0, QObject *parent = Q_NULLPTR);

Before you start asking about Q_NULLPTR in a comment, it is not magical. 在开始在评论中询问Q_NULLPTR之前,这不是魔术。 It is a hidden gem, but it is possible to use it freely as the maintainer said it will not break. 它是一个隐藏的宝石,但由于维护人员说它不会破裂,因此可以自由使用它。 It simply falls back to 0 without C++11 or later support, otherwise it is defined to nullptr , so your software will work with both. 如果没有C ++ 11或更高版本的支持,它会简单地回落为0 ,否则将其定义为nullptr ,因此您的软件将可以同时使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM