Qt解决error: use of deleted function和is private within this context

file

mainwindow.h

#include <QMainWindow>
#include <QLCDNumber>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_add_clicked();

    void on_pushButton_remove_clicked();

private:
    Ui::MainWindow *ui;
    QList <QLCDNumber> *m_pList;
};

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_pList = new QList <QLCDNumber>;
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_add_clicked()
{
    QLCDNumber *w = new QLCDNumber();
    m_pList->append(*w);
    ui->gridLayout->addWidget(w);

}

Compile error

略\QtCore\qlist.h:454: error: 'QLCDNumber::QLCDNumber(const QLCDNumber&)' is private within this context
     if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) n->v = new T(t);
                                                                 ^~~~~~~~
略\QtCore\qlist.h:454: error: use of deleted function 'QLCDNumber::QLCDNumber(const QLCDNumber&)'
     if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) n->v = new T(t);
                                                                 ^~~~~~~~

Resolution process

 By being given, we found two error are literally constructor is private and the use of destructors . The first one is easy to understand, is where you can not use private function uses a private function to get the error, did not understand the meaning of the second sentence, then down further inquiries, file qlist.h being given in the relevant code, / * number- - * / represents the number of line compiler errors,

template <typename T>
Q_INLINE_TEMPLATE void QList<T>::node_construct(Node *n, const T &t)
{
   /*454--*/ if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) n->v = new T(t);
   /*455--*/ else if (QTypeInfo<T>::isComplex) new (n) T(t);
#if (defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__IBMCPP__)) && !defined(__OPTIMIZE__)
    // This violates pointer aliasing rules, but it is known to be safe (and silent)
    // in unoptimized GCC builds (-fno-strict-aliasing). The other compilers which
    // set the same define are assumed to be safe.
   /*460--*/ else *reinterpret_cast<T*>(n) = t;
#else
    // This is always safe, but penaltizes unoptimized builds a lot.
    else ::memcpy(n, static_cast<const void *>(&t), sizeof(T));
#endif
}

 Errors found by the above-mentioned documents,

if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) n->v = new T(t);

 This triggers the sentence is private within this context, then a further inquiry QLCDNumber :: QLCDNumber (const QLCDNumber &) itself copy constructor, discover QLCDNumber comprising QLCDNumber parent (QFrame / QWidget / QObject) are not public (public) copy constructors, but found inside QLCDNumber class has a private macro,

private:
    Q_DISABLE_COPY(QLCDNumber)

 Retroactive to continue the macro,

/*
   Some classes do not permit copies to be made of an object. These
   classes contains a private copy constructor and assignment
   operator to disable copying (the compiler gives an error message).
*/
#define Q_DISABLE_COPY(Class) \
    Class(const Class &) Q_DECL_EQ_DELETE;\
    Class &operator=(const Class &) Q_DECL_EQ_DELETE;

 Found here, according to the above comments can know the cause of a error appeared. Call append QList of the time, you want to trigger the prohibition of copy constructor provoked the error.
 The solution is simple, that is, outside QLCDNumber Wrap an circumvent the copy constructor ring. Relatively easily, it may be QList <QLCDNumber> to QList <QLCDNumber *>.

Queries the root cause

 Although it is known why the error, but do not know why a normal class has no copy constructor, so continue to check documents. See the following passage in the contents QObject,

No Copy Constructor or Assignment Operator
QObject has neither a copy constructor nor an assignment operator. This is by design. Actually, they are declared, but in a private section with the macro Q_DISABLE_COPY(). In fact, all Qt classes derived from QObject (direct or indirect) use this macro to declare their copy constructor and assignment operator to be private. The reasoning is found in the discussion on Identity vs Value on the Qt Object Model page.
The main consequence is that you should use pointers to QObject (or to your QObject subclass) where you might otherwise be tempted to use your QObject subclass as a value. For example, without a copy constructor, you can't use a subclass of QObject as the value to be stored in one of the container classes. You must store pointers. 

 Said on paragraphs introduce Qt object model can be found in the cause, and suggested that we use pointers to QObject (and QObject subclass), or else may try to QObject related objects used as the value. For example, there is no copy constructor, an object can not be related to the value stored QObject, the pointer must be stored in a container. This is the case raises issues discussed in this article.
 Then, I turn to the Qt Object Model (Object Model) is introduced, some found the following article, which is about to QObject should use the logo (identity, as I understand it, is to identify the pointer to an object) or value (value) discussion,

Qt Objects: Identity vs Value
Some of the added features listed above for the Qt Object Model, require that we think of Qt Objects as identities, not values. Values are copied or assigned; identities are cloned. Cloning means to create a new identity, not an exact copy of the old one. For example, twins have different identities. They may look identical, but they have different names, different locations, and may have completely different social networks.
Then cloning an identity is a more complex operation than copying or assigning a value. We can see what this means in the Qt Object Model.
A Qt Object...
might have a unique QObject::objectName(). If we copy a Qt Object, what name should we give the copy?
has a location in an object hierarchy. If we copy a Qt Object, where should the copy be located?
can be connected to other Qt Objects to emit signals to them or to receive signals emitted by them. If we copy a Qt Object, how should we transfer these connections to the copy?
can have new properties added to it at runtime that are not declared in the C++ class. If we copy a Qt Object, should the copy include the properties that were added to the original?
For these reasons, Qt Objects should be treated as identities, not as values. Identities are cloned, not copied or assigned, and cloning an identity is a more complex operation than copying or assigning a value. Therefore, QObject and all subclasses of QObject (direct or indirect) have their copy constructor and assignment operator disabled. 

 In these words due to the characteristics of the Qt object model, if the use of value, copy (copy) or assignment (=) when will bring a lot of trouble, therefore, all subclasses of QObject and QObject are disabled copy constructor and assignment operator.

in conclusion

 QObject related objects using a pointer value instead.

Published 60 original articles · won praise 18 · views 20000 +

Guess you like

Origin blog.csdn.net/BadAyase/article/details/103407528