Russian Qt Forum
Ноябрь 24, 2024, 02:55 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: [Решено] Использование std::shared_ptr и std::unique_ptr c Qt объектами  (Прочитано 24478 раз)
8Observer8
Гость
« : Июнь 18, 2014, 14:28 »

Привет!

Захотел начать применять std::shared_ptr для Qt объектов, но сразу столнулся с проблемой. Компилятором выдаётся сообщение:

Цитировать
C:\Qt\Qt5.3.0\Tools\mingw482_32\i686-w64-mingw32\include\c++\ext\new_allocator.h:120: error: cannot allocate an object of abstract type 'QNetworkReply'
  { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
    ^

Код
C++ (Qt)
#ifndef DOWNLOADER_H
#define DOWNLOADER_H
 
#include <memory>
 
#include <QObject>
#include <QString>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetWorkAccessManager>
 
class Downloader : public QObject
{
   Q_OBJECT
 
   Downloader( )
   {
//        connect( m_reply, SIGNAL( finished( ) ),
//                 this, SLOT(replyFinished( ) ) );
   }
 
   void fetch( const QString &url )
   {
       std::shared_ptr<QNetworkAccessManager>
               manager( new QNetworkAccessManager( this ) );
 
       m_reply = std::make_shared<QNetworkReply>( manager->
                                                  get( QNetworkRequest( QUrl( url ) ) ) );
       //m_reply = manager->get( QNetworkRequest( QUrl( url ) ) );
   }
 
signals:
   void signalWithContent( QString * );
 
private slots:
   void replyFinished( )
   {
       QByteArray data = m_reply->readAll( );
       QString content( data );
       emit signalWithContent( &content );
   }
 
private:
   std::shared_ptr<QNetworkReply> m_reply;
   //QNetworkReply *m_reply;
};
 
#endif // DOWNLOADER_H
 
« Последнее редактирование: Июнь 23, 2014, 11:20 от 8Observer8 » Записан
vizir.vs
Гость
« Ответ #1 : Июнь 18, 2014, 14:42 »

Если я не ошибаюсь, то QNetworkReply является абстрактным классом, у него чистая виртуальная функция abort. Нельзя создавать объекты класса QNetworkReply.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #2 : Июнь 18, 2014, 14:56 »

28Observer8
Что по вашему делает эта строка?

Код
C++ (Qt)
m_reply = std::make_shared<QNetworkReply>( manager->get( QNetworkRequest( QUrl( url ) ) ) );
Записан
8Observer8
Гость
« Ответ #3 : Июнь 18, 2014, 15:17 »

Если я не ошибаюсь, то QNetworkReply является абстрактным классом, у него чистая виртуальная функция abort. Нельзя создавать объекты класса QNetworkReply.
Хм.. и правда. А почему мы тогда можем создавать объект этого класса через указатель? Как в этом коде:
Код
C++ (Qt)
         QNetworkReply *m_reply;
         QNetworkAccessManager *manager = new QNetworkAccessManager( this );
         m_reply = manager->get( QNetworkRequest( QUrl( url ) ) );
 

А вот так нельзя:
Код
C++ (Qt)
         QNetworkReply *m_reply = new QNetworkReply( this );
[code]
 
[quote author=Old link=topic=27203.msg196820#msg196820 date=1403092573]
28Observer8
Что по вашему делает эта строка?
 
[code=cpp]m_reply = std::make_shared<QNetworkReply>( manager->get( QNetworkRequest( QUrl( url ) ) ) );
[/quote]

Результатом этой команды: manager->get( QNetworkRequest( QUrl( url ) ) ) будет указатель на объект QNetworkReply. Потом этот указатель преобразуется в std::shared_ptr<QNetworkReply>. А уже этим преобразованным указателем инициализируется переменная m_reply. Всё таки нельзя создать std::shared_ptr<QNetworkReply>? Потому что QNetworkReply - это абстрактный класс?[/code][/code]
« Последнее редактирование: Июнь 18, 2014, 15:31 от 8Observer8 » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #4 : Июнь 18, 2014, 15:22 »

Результатом этой команды: manager->get( QNetworkRequest( QUrl( url ) ) ) будет указатель на объект QNetworkReply. Потом этот указатель преобразуется в std::shared_ptr<QNetworkReply>. А уже этим преобразованным указателем инициализируется переменная m_reply. Всё таки нельзя создать std::shared_ptr<QNetworkReply>? Потому что QNetworkReply - это чисто виртуальный класс?
Нет.
Эта строка пытается создать (make) объект класса QNetworkReply, передав в качестве параметра конструктору указатель возвращаемый этим: manager->get( QNetworkRequest( QUrl( url ) ) );

Поэтому, у вас ничего не получается. А создать shared_ptr на объект QNetworkReply можно.
Записан
8Observer8
Гость
« Ответ #5 : Июнь 18, 2014, 15:32 »

А почему так можно:

Код
C++ (Qt)
         QNetworkReply *m_reply;
         QNetworkAccessManager *manager = new QNetworkAccessManager( this );
         m_reply = manager->get( QNetworkRequest( QUrl( url ) ) );
 

А так нельзя:
Код
C++ (Qt)
         QNetworkReply *m_reply = new QNetworkReply( this );
 
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #6 : Июнь 18, 2014, 15:37 »

А так нельзя:
Потому, что QNetworkReply чисто виртуальный класс.
А в методе get создается объект класса одного из его наследников, поэтому их создавать можно.
Это, как бы, основы основ ООП в C++.
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #7 : Июнь 18, 2014, 15:41 »

потому что внутри создаются и возвращаются объекты приватных классов-наследников QNetworkReply. можно было просто заглянуть в исходники Улыбающийся
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
vizir.vs
Гость
« Ответ #8 : Июнь 18, 2014, 15:45 »

manager->get( QNetworkRequest( QUrl( url ) ) ); возвращает указатель на потомка QNetworkReply, но не сам QNetworkReply. Самого объекта QNetworkReply никогда не было и не будет. Это абстракция.
Записан
8Observer8
Гость
« Ответ #9 : Июнь 18, 2014, 15:56 »

В исходниках я нашёл:
Код
C++ (Qt)
/*!
   Posts a request to obtain the contents of the target \a request
   and returns a new QNetworkReply object opened for reading which emits the
   \l{QIODevice::readyRead()}{readyRead()} signal whenever new data
   arrives.
 
   The contents as well as associated headers will be downloaded.
 
   \sa post(), put(), deleteResource(), sendCustomRequest()
*/

QNetworkReply *QNetworkAccessManager::get(const QNetworkRequest &request)
{
   return d_func()->postProcess(createRequest(QNetworkAccessManager::GetOperation, request));
}
 

Но мне это не о чём не говорит... Хорошо, допустим, что get() возвращает указатель на объект класса потомка от QNetworkReply. Как узнать, какого потомка мне написать вместо вопросиков:
Код
C++ (Qt)
         m_reply = std::make_shared<???>( manager->
                                                    get( QNetworkRequest( QUrl( url ) ) ) );
 
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #10 : Июнь 18, 2014, 16:00 »

Как узнать, какого потомка мне написать вместо вопросиков:
Здесь не нужен make_shared. Объект ответа уже сконструирован внутри get.
Записан
vizir.vs
Гость
« Ответ #11 : Июнь 18, 2014, 16:03 »

а зачем вообще здесь make_shared? заюзай reset
Код:
        
m_reply.reset(manager->get( QNetworkRequest( QUrl( url ) ) ) );
« Последнее редактирование: Июнь 18, 2014, 16:06 от vizir.vs » Записан
8Observer8
Гость
« Ответ #12 : Июнь 18, 2014, 16:06 »

Как узнать, какого потомка мне написать вместо вопросиков:
Здесь не нужен make_shared. Объект ответа уже сконструирован внутри get.

Проблема в том, что я не могу написать так:
Код
C++ (Qt)
         std::shared_ptr<QNetworkReply> m_reply (manager->get( QNetworkRequest( QUrl( url ) ) ) );
 

У меня переменная m_reply объявляется в секции private. А там нельзя инициализировать объекты.
Записан
vizir.vs
Гость
« Ответ #13 : Июнь 18, 2014, 16:09 »

Что значит нельзя инициализировать в секции приват? Смотри мой предыдущий ответ.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #14 : Июнь 18, 2014, 16:12 »

У меня переменная m_reply объявляется в секции private. А там нельзя инициализировать объекты.
Вначале стоит изучить язык C++. У вас каша в голове. Не обижайтесь. Подмигивающий
Записан
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.388 секунд. Запросов: 22.