Меню

Qt use of deleted function ошибка

This topic has been deleted. Only users with topic management privileges can see it.

  • Hi all,
    I have a Song class like this:

    #include <QObject>
    class Song : public QObject
    {
        Q_OBJECT
    public:
        Song(const QString &title, const QString &singer, const QString &source, const QString &albumArt);
        explicit Song(QObject *parent = nullptr);
        Q_INVOKABLE QString title() const;
        QString singer() const;
        QString source() const;
        QString album_art() const;
    
    private:
        QString m_title;
        QString m_singer;
        QString m_source;
        QString m_albumArt;
    };
    

    This returned some errors below:

    'QObject::QObject(const QObject&)' is private within this context
    use of deleted function 'QObject::QObject(const QObject&)'
    

    Why I got these errors and how can I deal with it? Thanks for your help

    Regard


  • hi @lucas_1603,

    can we see your .cpp also?

    Have you added your definition of explicit Song(QObject *parent = nullptr);
    definition in .cpp?


  • @sharath
    Yes, here it is:

    #include <song.h>
    Song::Song(QObject *parent) : QObject (parent)
    {
        this->title() = "Hello World";
        this->singer() = "Dac Luc";
        this->source() = "lll";
        this->album_art() = "qrc:/Image/Hongkong1.png";
    }
    Song::Song(const QString &title, const QString &singer, const QString &source,  const QString &albumArt)
    {
        m_title = title;
        m_singer = singer;
        m_source = source;
        m_albumArt = albumArt;
    }
    
    Q_INVOKABLE QString Song::title() const
    {
        return m_title;
    }
    
    QString Song::singer() const
    {
        return m_singer;
    }
    
    QString Song::source() const
    {
        return m_source;
    }
    
    QString Song::album_art() const
    {
        return m_albumArt;
    }
    

  • @lucas_1603 said in error: «‘QObject::QObject(const QObject&)’ is private» and «use of deleted function ‘QObject::QObject(const QObject&)'»:

    this->title() = "Hello World";
    this->singer() = "Dac Luc";
    this->source() = "lll";
    this->album_art() = "qrc:/Image/Hongkong1.png";
    

    Nope! Those are getter functions, hence the error message! You need to write setters too, as Qt does for all properties like these, to be called like:

        this->setTitle("Hello World");
    

  • @jonb
    After added those setter functions and now my .cpp became like:

    #include <song.h>
    Song::Song(QObject *parent) : QObject (parent)
    {
        this->setTitle("Hello world");
        this->setSinger("Dac Luc");
        this->setSource("lll");
        this->setAlbumArt("qrc:/Image/Hongkong1.png");
    }
    Song::Song(const QString &title, const QString &singer, const QString &source,  const QString &albumArt)
    {
        m_title = title;
        m_singer = singer;
        m_source = source;
        m_albumArt = albumArt;
    }
    
    Q_INVOKABLE QString Song::title() const
    {
        return m_title;
    }
    
    QString Song::singer() const
    {
        return m_singer;
    }
    
    QString Song::source() const
    {
        return m_source;
    }
    
    QString Song::album_art() const
    {
        return m_albumArt;
    }
    

    But the errors are still the same


  • @lucas_1603 Where exactly do you get the error?
    The problem: QObject instances are NOT copyable.


  • @jsulm I think I’m getting trouble with Song class but actually I’m not sure about that because my project has other classes too. But I just see the errors in Song class now

    0_1568630374154_5f945232-7a62-4a16-8251-6caa978974c4-image.png


  • @lucas_1603
    I’m not an expert C++-er, but:

    • Did you re-run qmake after adding the Q_OBJECT macro to the file?

    • Song::Song(const QString &title, const QString &singer, const QString &source, const QString &albumArt)
      Does this constructor not need to invoke : QObject (parent) or your : Song(parent)? (I’m not sure about this one, but I’m thinking you need something like this?)


  • @jonb Thanks a lot, I’ll try to find it out


  • @lucas_1603 Your Song class is QObject based and thus not copyable. You’re apparently trying to make a copy of it.
    Double click at the first error line and see what is there.


  • @jsulm I don’t know what you mean by said that I’m trying to make a copy of it. I actually didn’t assign any ones to others!


  • Hi,

    Are you maybe using the copy constructor somewhere ?


  • @sgaist Nope, I don’t use it in my project and I’m quite sure about that ^^.
    I really want to know what does the error use of deleted function 'Song::Song(const Song&)' mean.


  • It means that somewhere in your code you are using the copy constructor which is disabled since QObject objects cannot be copied.


  • @lucas_1603 said in error: «‘QObject::QObject(const QObject&)’ is private» and «use of deleted function ‘QObject::QObject(const QObject&)'»:

    Nope, I don’t use it in my project and I’m quite sure about that ^^.

    The copy constructor is invoked when you try to assign one Song object to another, for example:

    Song s1("Happy Birthday to You", "Me", "/path/to/song", "/path/to/art");
    
    Song s2(s1);  // copy-constructor invoked here
    Song s3 = s1; // operator=() and copy-constructor invoked here
    

    I really want to know what does the error use of deleted function 'Song::Song(const Song&)' mean.

    It means your code contains something like s2 or s3 above.

    • Song::Song(const Song&) is the copy-constructor
    • A «deleted function» is a function which the creator has removed/deleted from the class — QObjects are not allowed to have copy-constructors. See https://thispointer.com/c11-c14-delete-keyword-and-deleted-functions-with-use-cases-examples/ for more info

  • @jksh Yep, I got it. I realized what all you guys said.

    So I change the approach to my project now, assume that I have a PlaylistModel class:

    #include <QAbstractListModel>
    class PlaylistModel : public QAbstractListModel
    {
        Q_OBJECT
    
    public:
        enum Roles {
            TitleRole = Qt::UserRole + 1,
            SingerRole,
            SourceRole,
            AlbumArtRole
        };
    
        explicit PlaylistModel(QObject *parent = nullptr);
    
        int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    
        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
        void addSong(Song &song);
    
    protected:
        QHash<int, QByteArray> roleNames() const override;
    
    private:
        QList<Song> m_data;
    };
    

    Now I want to access m_data (is the private attribute) from QML file, how can I do that?

    Thanks a lot for your help.


  • @lucas_1603
    You can only access private variables in the class which defines them. So expose a getter/setter if you really need to. But since QAbstractListModel already has data() & setData() methods you would normally go via those.



  • @jksh Yes, it compiled.
    @JonB As you said, I can access m_data via data() and setData() method. In data(), I have to assign QModelIndex &index and int role to it .
    How I can use data() method with enum TitleRole?


  • You should override roleNames method in your model:

    QHash<int, QByteArray> PlaylistModel::roleNames() const
    {
        static QHash<int, QByteArray>* ret = nullptr;
        if (ret)
            return *ret;
    
        ret = new QHash<int, QByteArray>();
        (*ret)[TitleRole] = "title";
        ...
    
        return *ret;
    }
    

    Then in QML you can use them as model property: model.title.


  • @intruderexcluder yes, I overrided it. When I use PlaylistModel as a model in QML, I actually just want to access m_data variable, not all of PlaylistModel attributes.
    Any suggestions to do that? Thanks a lot


  • You are probably doing something wrong, but you can at any time simply add slot or invokable method to access any data.


  • @lucas_1603 said in error: «‘QObject::QObject(const QObject&)’ is private» and «use of deleted function ‘QObject::QObject(const QObject&)'»:

    Yes, it compiled

    I actually just want to access m_data variable, not all of PlaylistModel attributes.

    Is Song still a subclass of QObject?


  • @jksh No, it’s not now. I think I’m doing right way in this time ^^
    The challenge now is accessing to m_data to get title, singer, source, album_art.


  • @lucas_1603 said in error: «‘QObject::QObject(const QObject&)’ is private» and «use of deleted function ‘QObject::QObject(const QObject&)'»:

    I think I’m doing right way in this time ^^

    There’s often more than 1 way to achieve something; some are just easier or more efficient than others 🙂

    The challenge now is accessing to m_data to get title, singer, source, album_art.

    I see that you’ve implemented a Model. The idea behind a model is that you shouldn’t need to access the internal data structure directly. Instead, you use the model’s standard interface (rows, columns, and maybe roles) to access individual fields.

    In your example, you can treat each Row as an individual song. You can also treat each Column as a song field (e.g. Col 1 = Title, Col 2 = Singer, etc.). Older examples use Roles instead of Columns

    In QML, you normally don’t call data() and setData() directly; you let the View and Delegate call them for you.

    Spend some time getting to know the model-view framework first:

    • https://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html
    • https://doc.qt.io/qt-5/qtquick-models-objectlistmodel-example.html
      • https://code.qt.io/cgit/qt/qtdeclarative.git/tree/examples/quick/models/objectlistmodel?h=5.13

    This is quite a lengthy topic, so it’s not something that we can teach you over a few forum posts. You need to spend time going through examples and modifying them to see how they behave. trying things out.


  • @jksh Thank you so much
    All you guys helped me a lot and I really appreciate it.
    I’ll spend more time to learn more about model-view framework to see how really they work.


  • 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

    LQtCoreqlist.h:454: error: 'QLCDNumber::QLCDNumber(const QLCDNumber&)' is private within this context
         if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) n->v = new T(t);
                                                                     ^~~~~~~~
    LQtCoreqlist.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.

    If you try to copy a class that derives from a QObject it will result in a compiler error, e.g.

    class MyClass : public QObject {
      Q_OBJECT
    } my_class;
    
    auto my_class_copy = my_class;
    

    with Qt5 and using C++11 (supporting =delete):

    error: use of deleted function ‘MyClass::MyClass(const MyClass&)’

    or with earlier versions:

    error: ‘QObject::QObject(const QObject&)’ is private within this context`

    This behaviour is by design. But why is the copy constructor (as well as the assignment operator) deleted? What if you still want to copy it? If it’s not copyable is it then movable? The following post will examine these questions as well as explore whether it’s a good practice to repeat the deletion in the custom subclass. Let’s dive in!

    There are several reasons why a QObject can’t be copied. The two biggest reasons are:

    • QObjects usually communicate with each other using the signals and slots mechanism. It’s unclear whether the connected signals and/or slots should be transferred over to the copy. If they would be transferred over, it would imply that other QObjects would automatically subscribe to the copy. This would most likely lead to confusion and unwanted side-effects for the developers.
    • QObjects are organised in object trees. Usually one instance of a QObject has one parent and several children. Where should the copy be organised in this hierarchy? Should the children (and grandchildren…) also be copied?

    Other reasons, but perhaps less critical, are:

    • A QObject can be considered unique by giving it a name which could be used as a reference key, i.e. by setting the QObject::objectName(). If the name is set, it’s unclear which name should be given to the copy.
    • QObjects can be extended with new properties during runtime. Should these new properties also be inherited by the copy?

    In general, QObjects are referred to by their pointer address by other objects. For example, this is the case in the aforementioned signals and slots mechanism. Because of this, QObjects can’t be moved; connections between them would then be lost. In the source code of QObject, we can see that the are no move constructor or move assignment operator declared. However, since the copy constructor is deleted, the move constructor won’t be implicitly generated and an compiler error will be reported if a developer attempts to move a QObject.

    So you can’t copy and you can’t move a QObject, but what if you desire to copy the underlying data (or properties)? Qt’s documentation distinguish between two object types in the Qt Object Model: value and identity objects. Value objects, such as QSize, QColor and QString are objects that can be copied and assigned. In contrast, the identity objects can’t be copied but can be cloned. As you might have guessed, an example of an identity object is the QOBject or any class that derives from it. The meaning of cloning can be read from the official documentation:

    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.

    My understanding of cloning is that you could expose a clone()-function in a subclass which creates a new identity but not a real copy, i.e:

    class MyClass : public QObject {
      Q_OBJECT
    
    public:
      MyClass* clone() {
        auto copy = new MyClass;
        //copy only data
        return copy;
      }
    
    private:
      //data
    };
    ...
    
    auto my_class = new MyClass;
    auto my_class_clone = my_class->clone();
    

    Although this is possible to do, I wouldn’t recommend it. It could lead to unwanted side-effects as Qt developers will most likely have assumptions about QObjects. If you have the need of creating a clone, I would suggest to have a look at your overall design and architecture instead. Perhaps the data could be decoupled or factored out?

    Repeating Q_DISABLE_COPY(Class) in the subclass

    On stackoverflow it has been suggested to always redeclare the macro Q_DISABLE_COPY(Class) in your own class, i.e.:

    class MyClass : public QObject {
      Q_OBJECT
      Q_DISABLE_COPY(MyClass) // See macro below
      public:
        QObject() {}
    };
    
    #define Q_DISABLE_COPY(Class) 
      Class(const Class &); 
      Class &operator=(const Class &);
    

    The main reason, as mentioned in the stackoverflow post, is to improve the error message. Without the macro, the following error message is reported using Qt4:

    error: ‘QObject::QObject(const QObject&)’ is private within this context`

    With the macro, it’s reporting:

    error: ‘MyClass::MyClass(const MyClass&)’ is private within this context`

    The last error message is far more easier to understand for someone who’s new to Qt.

    However from Qt5, the macro was changed and declared as:

    #ifdef Q_COMPILER_DELETE_MEMBERS 
    # define Q_DECL_EQ_DELETE = delete
    #else
    # define Q_DECL_EQ_DELETE
    #endif
    
    #define Q_DISABLE_COPY(Class) 
      Class(const Class &) Q_DECL_EQ_DELETE;
      Class &operator=(const Class &) Q_DECL_EQ_DELETE;
    

    Without adding the macro in the subclass, the following error message is displayed:

    error: use of deleted function ‘MyClass::MyClass(const MyClass&)’

    The copy constructor and assignment operator have now been declared with =delete instead of just being private, resulting in a preferred error message.

    Even though the error message has improved, I still believe it’s valuable to redeclare the macro in the derived class, as it documents the behaviour of the class. Someone who’s new to Qt can quickly understand the intended usage: the object shouldn’t (and can’t) be copied!

    Since Qt 5.13 there is a macro that disables both copying and moving the object. The macro makes the wanted behaviour even more explicit and therefore preferred to use. See Q_DISABLE_COPY_MOVE


    parsecer

    3 / 3 / 2

    Регистрация: 19.07.2015

    Сообщений: 74

    1

    11.02.2016, 00:27. Показов 8686. Ответов 3

    Метки нет (Все метки)


    У меня есть два класса: Dog и Owner. В классе Dog есть public static член, имеющий тип Owner & (ссылка на экземпляр класса Owner). Но при попытке это все реализовать, возникает ошибка «use of deleted function ‘Dog& Dog::operator=(const Dog&)». Вот код классов и их конструкторов:

    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    class Dog 
        {
           private:
             Owner & m_owner;
             ...
           public:
               static Owner & m_breeder;
             ...
        }
     
    class Owner
        {private:
             ...
         public:
             ...
          }

    dog_methods.cpp

    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    
     {
        #include "dog_class.h"
        #include <iostream>
        #include <cstdlib>
        #include <string>
        #include <ctime>
     
        Owner breeder("breeder");
        Owner & Dog::m_breeder=breeder;
        //methods here
        Dog () : m_owner(m_breeder) {}
     
    Dog::Dog(std::string name, int size, int status, int loyalty, int sex, int price, std::vector<Dog> * market, Owner & owner) : m_owner(owner)
    {
    m_name=name;
    m_size=size;
    m_status=status;
    m_loyalty=loyalty;
     
    m_sex=sex;
    m_price=price;
    m_market=market; //pointer to the market
    m_market->push_back(*this);
    //break_out();
     }
     
     
     
      Dog::Dog() : m_owner(m_breeder)
    {
    m_name="Fang";
    srand(time(NULL));
    m_size=(rand()%10)+1; //small: random number from 1 to 10;
    m_status=0; //not owned
    m_loyalty=(rand()%10)+1; //from 1 to 10
    Owner no_one("no_one");
    //m_owner=no_one;
    m_sex=rand()%2; //rand 0 or 1;
    m_price=rand()%1001; //0 - 1000;
    //show_data();
    //break_out();
     }

    owner_methods.cpp

    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    
    Owner::Owner()
    {
     
    m_name="random";
    m_goodness=(rand()%10+1);
    m_size=(rand()%10+1);
    m_money=rand()%1001;
    m_agility=(rand()%10+1);
    m_int=(rand()%10+1);
    //std::cout<<"Hi! I am the "<<m_name<<std::endl;
     }
      Owner::Owner(std::string name)
     {
     if (name=="no one")
     {
    m_name="no one";
    m_goodness=0;
    m_size=0;
    m_money=0;
    m_agility=0;
    m_int=0;
    std::cout<<"Hi! I am the "<<m_name<<std::endl;
       }
       else
      {
    m_name=name;
    m_goodness=(rand()%10+1);
    m_size=(rand()%10+1);
    m_money=rand()%1001;
    m_agility=(rand()%10+1);
    m_int=(rand()%10+1);
    std::cout<<"The '"<<m_name<<"' owner made"<<std::endl;
        }
      }
     
     
     Owner::Owner(std::string name, int goodness, int size, int money, int    agility, std::vector<Dog> doglist)
      {
    m_name=name;
    m_size=size;
    m_money=money;
    m_agility=agility;
    for (int i=0;  i<doglist.size();i++)
        m_doglist.push_back(doglist[i]);
      }

    __________________
    Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



    0



    16466 / 8966 / 2198

    Регистрация: 30.01.2014

    Сообщений: 15,567

    11.02.2016, 00:34

    2

    Лучший ответ Сообщение было отмечено parsecer как решение

    Решение

    parsecer, оператор присваивания в классе Dog опиши явно. Он deleted потому что ссылки не присваиваются (не переназначаются). Обыграй это как-то сам в операторе.



    1



    3 / 3 / 2

    Регистрация: 19.07.2015

    Сообщений: 74

    11.02.2016, 00:42

     [ТС]

    3

    Спасибо за ответ, а что вызвало данную ошибку? В main присваивания Dog=Dog нигде не используется.



    0



    16466 / 8966 / 2198

    Регистрация: 30.01.2014

    Сообщений: 15,567

    11.02.2016, 00:45

    4

    Цитата
    Сообщение от parsecer
    Посмотреть сообщение

    Спасибо за ответ, а что вызвало данную ошибку?

    Вектор требует от своих элементов быть либо copy-assignable, либо move-assignable.



    1



    Я строю приложение с Qt5. Моя программа собирается и работает нормально, но есть конфликт между двумя потоками, обращающимися к структуре данных. У меня есть QList объектов CanMessage, и я хочу защитить некоторые данные внутри него, используя QMutex. Однако, как только я добавляю QMutex в свое определение класса, я получаю ошибки:

    QList.h: `error: C2280:
    'CanMessage::CanMessage(const CanMessage &)': attempting to reference a deleted function`.
    

    Вот мой canmessage.h файл:

    #ifndef CANMESSAGE_H
    #define CANMESSAGE_H
    
    #include <QObject>
    #include <QMutex>
    #include "cansignal.h"
    class CanMessage
    {
    public:
    CanMessage();
    /* snip - public function prototypes */
    
    private:
    /* snip - private prototypes and data */
    QMutex m_messageMutex;
    };
    
    #endif // CANMESSAGE_H
    

    А также cansignal.h:

    #ifndef CANSIGNAL_H
    #define CANSIGNAL_H
    
    #include <QObject>
    #include <QDebug>
    #include <QByteArray>
    
    class CanSignal
    {
    public:
    CanSignal();
    
    CanSignal(QString &signalName, quint8 &signalLength, quint8 &signalStartBit,
    float &offset, float &factor, bool &isBigEndian, bool &isFloat, bool &isSigned)
    {
    this->m_name = signalName;
    this->m_length = signalLength;
    this->m_startBit = signalStartBit;
    this->m_offset = offset;
    this->m_factor = factor;
    this->m_isBigEndian = isBigEndian;
    this->m_isFloat = isFloat;
    this->m_isSigned = isSigned;
    }
    
    bool setName(QString &signalName);
    bool setBitLength(quint8 &length);
    bool setStartBit(quint8 &startBit);
    bool setOffset(float &offset);
    bool setFactor(float &factor);
    bool setEndianess(bool &isBigEndian);
    bool setIsFloat(bool &isFloat);
    bool setIsSigned(bool &isSigned);
    void setValid();
    void setInvalid();
    void setEngineeringData(float data);
    
    QString getName();
    quint8 getBitLength();
    quint8 getStartBit();
    float getOffset();
    float getFactor();
    float getData();
    bool isBigEndian();
    bool isFloat();
    bool isSigned();
    bool getSignalValidity();private:
    QString m_name;
    quint8 m_length;
    quint8 m_startBit;
    float m_offset;
    float m_factor;
    float m_data_float = 0;
    bool m_isBigEndian;
    bool m_isFloat;
    bool m_isSigned;
    // Set After everything in signal is filled
    bool m_isSignalValid = false;
    };
    
    #endif // CANSIGNAL_H
    

    0

    Решение

    CanMessage::CanMessage(const CanMessage &)
    

    это конструктор копирования, который, очевидно, используется для помещения элемента в список. Это не будет работать, так как QMutex не является на самом деле копируемый.

    Как вы решите это, зависит от ряда вещей. Возможно, самый простой способ будет изменить CanMessage так что он имеет динамический мьютекс (конечно, созданный в конструкторе).

    Затем создайте для него конструктор копирования, который сначала блокирует источник объект мьютекс затем динамически распределяет новый мьютекс в целевом объекте.

    Таким образом, вы можете гарантировать, что старый объект будет «чистым» при копировании (потому что у вас есть его мьютекс), и не будет проблемы «попытки скопировать некопируемый элемент», так как сам мьютекс не скопировано. Смотрите сноску (a) для деталей.


    Следующий код, который представляет собой полный простой фрагмент, показывающий проблему, компилируется нормально, если вы оставите QMutex m_mutex; строка закомментирована:

    #include <QList>
    #include <QMutex>
    
    #include <iostream>
    
    class Xyzzy {
    private:
    int m_xyzzy;
    //QMutex m_mutex;
    public:
    Xyzzy() : m_xyzzy(0) {};
    Xyzzy(int val) : m_xyzzy(val) {};
    };
    
    int main() {
    QList<Xyzzy> myList;
    Xyzzy plugh;
    myList.push_back(plugh);
    return 0;
    }
    

    Однажды ты ун-комментарий В этой строке компилятор справедливо жалуется:

     error: use of deleted function 'Xyzzy::Xyzzy(const Xyzzy&)'
    

    (А) С точки зрения решения проблемы вы можете сделать что-то вроде:

    #include <QList>
    #include <QMutex>
    
    #include <iostream>
    
    class Xyzzy {
    private:
    int m_xyzzy;
    QMutex *m_mutex; // Now a pointer
    public:
    Xyzzy() : m_xyzzy(0) {
    m_mutex = new QMutex(); // Need to create in constructor.
    std::cout << "constructor " << m_mutex << 'n';
    };
    ~Xyzzy() {
    std::cout << "destructor " << m_mutex << 'n';
    delete m_mutex; // Need to delete in destructor.
    }
    Xyzzy(const Xyzzy &old) {
    old.m_mutex->lock();
    m_mutex = new QMutex(); // Need to make new one here.
    std::cout << "copy constructor from " << old.m_mutex
    << " to " << m_mutex << 'n';
    old.m_mutex->unlock();
    }
    };
    
    int main() {
    QList<Xyzzy> myList;
    Xyzzy plugh;
    myList.push_back(plugh);
    return 0;
    }
    

    Это работает правильно, согласно следующему тесту:

    constructor 0x21c9e50
    copy constructor from 0x21c9e50 to 0x21c9ec0
    destructor 0x21c9e50
    destructor 0x21c9ec0
    

    В реальном коде я бы, вероятно, выбрал умные указатели, а не сырые new/delete звонки, но это только для иллюстрации концепции. Кроме того, вам нужно будет обработать все другие возможности, которые создают новый объект из существующего, согласно правилу «три / пять / все, что идет дальше», в настоящее время (из памяти) ограничено членом назначения копирования. Xyzzy &operator=(const Xyzzy &old),

    1

    Другие решения

    Других решений пока нет …

    When compiling I get the following error, in QList . I’m using Qt 5.6.

    error: use of deleted function ‘Vitamin: Vitamin (const Vitamin &)’ current-> v = new T (* reinterpret_cast (src-> v))

    error: use of deleted function ‘Vitamin: Vitamin (const Vitamin &)’ new (current) T (* reinterpret_cast (src))

    error: use of deleted function ‘Vitamin: Vitamin (const Vitamin &)’ else if (QTypeInfo :: isComplex) new (n) T (t);

    error: use of deleted function ‘Vitamin & Vitamin :: operator = (const Vitamin &) ‘else * reinterpret_cast (n) = t;

    BaseClass

    Header

    #ifndefCOMPONETNUTRITIONAL#defineCOMPONETNUTRITIONAL#include<QObject>#include<QList>classComponentNutritional:publicQObject{Q_OBJECTpublic:explicitComponentNutritional(QObject*parent=0);~ComponentNutritional();QStringgetName();floatgetValue();floatgetDairyValue();QStringgetMeasure();protected:QStringname;floatvalue;floatdairyvalue;QStringmeasure;};#endif//COMPONETNUTRITIONAL

    Cpp

    #include"componetnutritional.h"
    
    #include <typeinfo>
    
    ComponentNutritional::ComponentNutritional(QObject *parent):QObject(parent)
    {
        this->name = typeid(this).name();
        this->dairyvalue = 0;
        this->measure = "";
        this->value = 0;
    }
    
    ComponentNutritional::~ComponentNutritional()
    {
    
    }
    
    QString ComponentNutritional::getName()
    {
        return this->name;
    }
    
    float ComponentNutritional::getValue()
    {
        return this->value;
    }
    
    float ComponentNutritional::getDairyValue()
    {
        return this->dairyvalue;
    }
    
    QString ComponentNutritional::getMeasure()
    {
        return this->measure;
    }
    
    

    Inheriting class

    Header

    
    #ifndef VITAMIN_H
    #define VITAMIN_H
    
    #include <QObject>
    #include "Library/Types/Base/componetnutritional.h"
    
    class Vitamin : public ComponentNutritional
    {
    public:
        explicit Vitamin(QObject *parent = 0);
        ~Vitamin();
        Q_INVOKABLE  Vitamin *setName(QString value);
        Q_INVOKABLE  Vitamin *setValue(float value);
        Q_INVOKABLE  Vitamin *setDairyValue(float value);
        Q_INVOKABLE  Vitamin *setMeasure(QString value);
    };
    
    class Vitamins: public QList<Vitamin>{
    };
    #endif // VITAMIN_H
    
    

    Cpp

    
    #include "vitamin.h"
    
    Vitamin::Vitamin(QObject *parent): ComponentNutritional(parent)
    {
    
    }
    
    Vitamin::~Vitamin()
    {
    
    }
    
    Vitamin *Vitamin::setName(QString value)
    {
        this->name = value;
        return this;
    }
    
    Vitamin *Vitamin::setValue(float value)
    {
        this->value = value;
        return this;
    }
    
    Vitamin *Vitamin::setDairyValue(float value)
    {
        this->dairyvalue = value;
        return this;
    }
    
    Vitamin *Vitamin::setMeasure(QString value)
    {
        this->measure = value;
        return this;
    }
    
    

    Solution

    
    #ifndef VITAMIN_H
    #define VITAMIN_H
    
    #include <QObject>
    #include "Library/Types/Base/componetnutritional.h"
    
    class Vitamin : public ComponentNutritional
    {
    public:
        explicit Vitamin(QObject *parent = 0);
        ~Vitamin();
        Q_INVOKABLE  Vitamin *setName(QString value);
        Q_INVOKABLE  Vitamin *setValue(float value);
        Q_INVOKABLE  Vitamin *setDairyValue(float value);
        Q_INVOKABLE  Vitamin *setMeasure(QString value);
    };
    
    class Vitamins: public QList<Vitamin*>{ //Alterado para ponteiro
    };
    #endif // VITAMIN_H
    
    

        

    asked by

    anonymous 08.06.2016 / 15:57

    0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии

    А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Qt platform plugin windows ошибка как исправить python
  • Qt platform plugin windows ошибка как исправить amd