Tag Archives: QT solves error

QT solves error: use of deleted function and 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);

}

A compiler error

L\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);
                                                                 ^~~~~~~~
L\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);
                                                                 ^~~~~~~~

To solve the process
By reporting an error, we know that the literal meaning of both errors is that the constructor is private and that the destructor is used. In qlist.h, if you use a private function, /*number- */ indicates the number of lines of compilation 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
}

According to the error in the above document,

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

This sentence triggers is private within this context, so further query QLCDNumber::QLCDNumber(const QLCDNumber&) Copy the constructor itself, found that there is no public copy constructor in QLCDNumber including QLCDNumber’s parent class (QFrame/QWidget/QObject), but found that there is a private macro inside QLCDNumber class,

private:
    Q_DISABLE_COPY(QLCDNumber)

Continue tracing 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;

At this point, you can see the reason for an error based on the above comment. When calling the append of QList, an attempt to trigger the forbidden copy constructor resulted in an error. The
solution is also simple: wrap a layer over the QLCDNumber to avoid the copy constructor loop. Quite simply, you can put QList < QLCDNumber > Instead of QList & lt; QLCDNumber* > .
Query root cause
You know why the error is being reported, but you don’t know why a normal class doesn’t have a copy constructor, so you go ahead and look at the documentation. In contents on QObject I see the following passage,

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. 

The previous section said that the Qt object model can be found in the introduction, and suggested that we use Pointers to QObject (and QObject subclasses), otherwise we might try to use QObject-related objects as values. For example, without a copy constructor, a qObject-related object cannot be stored as a value in the container; Pointers must be stored. It is this situation that leads to the question discussed in this article.
then, I turned to the introduction of Qt Object Model and found the following paragraph. This is a discussion about whether QObject should use identity (according to my understanding, an identity is a pointer to an Object) or value.

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. 

QObject and all subclasses of QObject disable copy constructors and assignment operators due to the nature of the Qt object model, which can cause a lot of confusion when using value, copying, or assignment (=).
conclusion
Qobject-related objects use Pointers instead of values.