Russian Qt Forum

Qt => Общие вопросы => Тема начата: 8Observer8 от Июнь 23, 2014, 12:16



Название: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: 8Observer8 от Июнь 23, 2014, 12:16
Привет!

У меня есть два объекта. Один класса Downloader, а другой Shower. В функции main() я соединяю сигнал одного, со слотом второго. Но при запуске получаю ошибку:
Цитировать
QObject::connect: No such slot QObject::replyFinished( ) in D:/Qt/QtIO/0009_HtmlWebSite/HtmlWebSite/Downloader.h:26

main.cpp
Код
C++ (Qt)
 
#include <iostream>
 
#include <QString>
#include <QObject>
#include <QCoreApplication>
 
#include "Shower.h"
#include "Downloader.h"
 
int main( int argc, char *argv[] )
{
   QCoreApplication app( argc, argv );
 
   Downloader downloader;
   Shower shower;
   QObject::connect( &downloader, SIGNAL( signalWithContent( QString* ) ),
                     &shower, SLOT( show( QString* ) ) );
 
   QString url = "http://qtobserver.freeoda.com/installing_netbeans.php";
   downloader.fetch( url );
 
   return app.exec();
}
 

Downloader.h
Код
C++ (Qt)
#ifndef DOWNLOADER_H
#define DOWNLOADER_H
 
#include <memory>
#include <string>
 
#include <QObject>
#include <QString>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
 
class Downloader : public QObject
{
 
public:
   Downloader( )
   {
       m_manager = std::unique_ptr<QNetworkAccessManager>( new QNetworkAccessManager( this ) );
   }
 
   void fetch( const QString &url )
   {
       m_reply.reset( m_manager->get( QNetworkRequest( QUrl( url ) ) ) );
       connect( m_reply.get( ), SIGNAL( finished( ) ),
                this, SLOT( replyFinished( ) ) );
   }
 
signals:
   void signalWithContent( QString *content );
 
private slots:
   void replyFinished( )
   {
       QByteArray data = m_reply->readAll( );
       QString content( data );
       emit signalWithContent( &content );
   }
 
private:
   std::unique_ptr<QNetworkReply> m_reply;
   std::unique_ptr<QNetworkAccessManager> m_manager;
};
 
#endif // DOWNLOADER_H
 

Shower.h
Код
C++ (Qt)
#ifndef SHOWER_H
#define SHOWER_H
 
#include <QObject>
#include <QString>
#include <QTextCodec>
#include <QByteArray>
#include <QDebug>
 
class Shower : public QObject
{
   Q_OBJECT
 
public slots:
   void show( QString *content )
   {
       qDebug() << *content;
   }
};
 
#endif // SHOWER_H
 


Название: Re: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: GreatSnake от Июнь 23, 2014, 12:19
В Downloader забыл вставить Q_OBJECT.
В чём глубокий смысл передавать QString по указателю?
Или очень сильно хочется получить падение?


Название: Re: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: 8Observer8 от Июнь 23, 2014, 12:30
Да, точно! Спасибо :)

В Qt-сигналах вроде всё передаётся через указатель. Или я что-то не понял?


Название: Re: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: GreatSnake от Июнь 23, 2014, 12:31
В Qt-сигналах вроде всё передаётся через указатель. Или я что-то не понял?
С чего это вдруг?


Название: Re: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: Zerkin от Июнь 23, 2014, 12:35
Да, точно! Спасибо :)

В Qt-сигналах вроде всё передаётся через указатель. Или я что-то не понял?

Непонятно, что Вы под этим подразумеваете. Может, стоит еще разок прочитать про это? http://doc.crossplatform.ru/qt/4.3.2/signalsandslots.html Без обид  ;)


Название: Re: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: GreatSnake от Июнь 23, 2014, 12:39
И ещё про Implicit Sharing (http://doc.crossplatform.ru/qt/4.7.x/implicit-sharing.html) не мешало бы тоже знать.


Название: Re: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: 8Observer8 от Июнь 23, 2014, 12:42
Да, какие уж там обиды? :) Спасибо!

Мне пример когда-то попадался, где по указателю была передача. А вообще-то, да. Смотрю, что по значению и по констрантной ссылке передают (хотя по ссылке - это тоже, что и по указателю). Почитаю, но сейчас не понимаю, почему и когда в моём примере может произойти падение? Здесь только по значению надо? Но объекты же живут...


Название: Re: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: GreatSnake от Июнь 23, 2014, 12:52
но сейчас не понимаю, почему и когда в моём примере может произойти падение? Здесь только по значению надо? Но объекты же живут...

Добавь к
Цитата: 8Observer8
   QObject::connect( &downloader, SIGNAL( signalWithContent( QString* ) ),
                      &shower, SLOT( show( QString* ) ) );
последний аргумент type равный Qt::QueuedConnection и увидишь.
Понятно, что скорее-всего в обычной практике так делать придётся редко, но думать всё равно нужно.

хотя по ссылке - это тоже, что и по указателю
Только не в случае Qt. Почему? - читай ссылку выше.


Название: Re: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: 8Observer8 от Июнь 23, 2014, 12:57
Приложение падает и выдаётся текст:
Цитировать
ASSERT: "alloc >= 0 && extra >= 0" in file tools\qbytearray.cpp, line 72
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.

Если есть время, то прошу объяснить. Конечно, пытаюсь понять по ссылкам и по документации (про "Qt::QueuedConnection").

Позже напишу, как я понял.


Название: Re: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: kambala от Июнь 23, 2014, 13:07
если параметр сигнала — временные данные (локальная переменная например), то они уже сдохнут к моменту прихода сигнала, и, вероятнее всего, указатель будет указывать на что-то другое или вовсе на мусор


Название: Re: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: Kurles от Июнь 23, 2014, 13:07
Приложение падает и выдаётся текст:
Цитировать
ASSERT: "alloc >= 0 && extra >= 0" in file tools\qbytearray.cpp, line 72
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.

Если есть время, то прошу объяснить. Конечно, пытаюсь понять по ссылкам и по документации (про "Qt::QueuedConnection").

Позже напишу, как я понял.
выход за границы массива обычно причина такого поведения.


Название: Re: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: 8Observer8 от Июнь 23, 2014, 13:12
Я просто думал, что в Qt хитрость какая-то есть :) Видимо, она и есть, только работает с константными ссылками, а не указателями.


Название: Re: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: GreatSnake от Июнь 23, 2014, 13:13
Я просто думал, что в Qt хитрость какая-то есть :) Видимо, она и есть, только работает с константными ссылками, а не указателями.
Понял неправильно.


Название: Re: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: 8Observer8 от Июнь 23, 2014, 13:17
Если по значению, то это дороже выходит? Или для сигналов-слотов - без разницы?
Код
C++ (Qt)
signals:
   void signalWithContent( const QString &content );
 

Код
C++ (Qt)
signals:
   void signalWithContent( QString content );
 


Название: Re: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: GreatSnake от Июнь 23, 2014, 13:23
Если по значению, то это дороже выходит? Или для сигналов-слотов - без разницы?
Читай внимательно о Implicit Sharing (http://doc.crossplatform.ru/qt/4.7.x/implicit-sharing.html) и не гадай.


Название: Re: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: 8Observer8 от Июнь 23, 2014, 13:26
Хорошо, спасибо! :)


Название: Re: QObject::connect: No such slot QObject::replyFinished( )
Отправлено: Igors от Июнь 23, 2014, 15:51
Если по значению, то это дороже выходит? Или для сигналов-слотов - без разницы?
Код
C++ (Qt)
signals:
   void signalWithContent( const QString &content );
 

Код
C++ (Qt)
signals:
   void signalWithContent( QString content );
 
Если DirectConnection - то все так же как в языке, передача по (часто константной) ссылке лучше. В остальных случаях надо считаться с возможностью что content будет уже удален к моменту получения сигнала. Тогда часто по значению (имплисит шара поможет) - но не всегда, напр
Код
C++ (Qt)
 
void signalWithContent( QString & content );
void signalWithContent( QString * content );
 
Если нам надо чтобы сигнал заполнил content - придется делать так, и позаботиться чтобы content был жив. Ничего плохого в этом нет. Как и во многих др случаях, какого-то единого правила здесь нет, надо делать по смыслу