2016-06-04 7 views
0

Я пытаюсь передать один общий указатель из класса QTGUI в класс Client и продолжать получать ошибки bad weak ptr. Я прочитал, что я не могу назначить shared_from_this() непосредственно в конструкторе, потому что указатель в этой точке не готов.Ошибка 'bad_weak_ptr'

У меня поэтому создана функция getptr, которая возвращает указатель объекта, чтобы впоследствии назначить его клиенту при последующем вызове. Однако, похоже, это не работает.

Что мне здесь не хватает? Заранее большое спасибо.

qtgui.hpp

#ifndef QTGUI_H 
#define QTGUI_H 

#include <QMainWindow> 
#include <QFileSystemWatcher> 

#include <boost/enable_shared_from_this.hpp> 
#include <boost/shared_ptr.hpp> 
#include <boost/signals2.hpp> 
#include <boost/bind.hpp> 

class Client; 

namespace Ui { 
class QTGUI; 
} 

class QTGUI : public QMainWindow, public boost::enable_shared_from_this<QTGUI> 
{ 
    Q_OBJECT 

public: 
    explicit QTGUI(QWidget *parent = 0); 
    ~QTGUI(); 

    void start(); 
    boost::shared_ptr<QTGUI> getptr(); 

    /* Signals */ 
    typedef boost::signals2::signal 
     <void (const char* ipaddress, const char* port)> start_connect; 
    typedef start_connect::slot_type start_connect_st; 

    boost::signals2::connection start_connect_ui(const start_connect_st& slot); 

private slots: 
private: 
    Ui::QTGUI *ui; 

    boost::shared_ptr<Client> client_; 

    start_connect sc_signal; 
}; 

#endif // QTGUI_H 

qtgui.cpp

#include "qtgui.h" 
#include "ui_qtgui.h" 

#include <iostream> 

#include <QHostAddress> 
#include <QRegExp> 
#include <QIntValidator> 
#include <QFileDialog> 

#include <unistd.h> 
#include <pwd.h> 
#include <sys/types.h> 

#include "../client/client.hpp" 


#include <boost/bind.hpp> 
#include <boost/thread.hpp> 

QTGUI::QTGUI(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::QTGUI), 
    connected_(false), 
    client_(new Client) 
{ 


    start(); 
} 

boost::shared_ptr<QTGUI> QTGUI::getptr() 
{ 
    return shared_from_this(); 
} 

void QTGUI::start() 
{ 

    client_->addui(getptr()); 
    client_->get_con_status(boost::bind(&QTGUI::connection_status, this, 
_1)); 
} 

boost::signals2::connection QTGUI::start_connect_ui(const start_connect_st& 
slot) 
{ 
    return sc_signal.connect(slot); 
} 

client.hpp

#ifndef CLIENT_HPP 
#define CLIENT_HPP 

#include <boost/asio.hpp> 
#include <boost/shared_ptr.hpp> 
#include <boost/enable_shared_from_this.hpp> 
#include <boost/scoped_ptr.hpp> 
#include <boost/thread.hpp> 

#include <boost/signals2.hpp> 

#include "../common/message.hpp" 

class QTGUI; 

class Client : public boost::enable_shared_from_this<Client> 
{ 
public: 
    Client(/*boost::shared_ptr<QTGUI> ui*/); 

    void addui(boost::shared_ptr<QTGUI> ptr); 


    /* Signals */ 
    typedef boost::signals2::signal<void (bool status)> connect_status; 
    typedef connect_status::slot_type connect_status_st; 

    boost::signals2::connection get_con_status(const connect_status_st& slot); 

private: 
    boost::shared_ptr<QTGUI> ui_; 
    boost::shared_ptr<boost::thread> thread_; 
    boost::shared_ptr<boost::asio::io_service> io_service_; 
    boost::shared_ptr<boost::asio::io_service::work> work_; 
    boost::shared_ptr<boost::asio::ip::tcp::socket> socket_; 

    connect_status cs_sig; 
}; 

#endif// client.hpp 

client.cpp

#include <boost/bind.hpp> 
#include <boost/bind/protect.hpp> 
#include <boost/function.hpp> 

#include <cstdio> /* sprintf */ 

#include "client.hpp" 
#include "../common/commands.hpp" 
#include "../common/kinotify.hpp" 
#include "../gui/qtgui.h" 

#include <functional> 
#include <unistd.h> 

Client::Client(/*boost::shared_ptr<QTGUI> ui*/): 
//ui_(ui), 
io_service_(new boost::asio::io_service), 
work_(new boost::asio::io_service::work(*io_service_)), 
connected_(false) 
{ 
    start(); 
} 
void Client::addui(boost::shared_ptr<QTGUI> ptr) 
{ 
    ui_ = ptr; 
    std::cout << "Connecting..." << std::endl; 
    ui_->start_connect_ui(boost::bind(&Client::post_connect, 
             shared_from_this(), _1, _2)); 
} 


void Client::start() 
{ 
    if(thread_) 
     return; 

    std::cout << "Creating new thread bruh" << std::endl; 
    thread_.reset(new boost::thread(
     boost::bind(&boost::asio::io_service::run, io_service_) 
    )); 
    std::cout << "start Thread ID [" << boost::this_thread::get_id() << 
    "]" << std::endl; 
} 

void Client::stop() 
{ 
    if(!thread_) 
     return; 

    std::cout << "Ending" << std::endl; 
    socket_->shutdown(boost::asio::ip::tcp::socket::shutdown_both); 
    socket_->close(); 
    io_service_->stop(); 
    thread_->join(); 
    io_service_->reset(); 
    thread_.reset(); 
} 

boost::signals2::connection Client::get_con_status(const connect_status_st& 
slot) 
{ 
    return cs_sig.connect(slot); 
} 

EDIT: добавить main.cpp

#include "qtgui.h" 
#include <QApplication> 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    QTGUI w; 
    w.start(); 
    w.show(); 

    return a.exec(); 
} 

ответ

2

Я прочитал, что я не могу назначить shared_from_this() непосредственно в конструкторе, потому что указатель в этой точке не готов.

Верно, вы не можете использовать shared_from_this(), пока объект не будет полностью построен. Только в этот момент назначается базовый weak_ptr. Ограничение не только напрямую от конструктора - вы все еще звоните shared_from_this до QTGUI s полностью построены. Тот факт, что вы используете функцию для извлечения из другой функции, не имеет значения.

Просто позвоните start() извне в класс после его создания. Это будет работать.


Сторона примечания: getptr() бесполезна. Просто используйте shared_from_this() напрямую.

+1

Другое примечание: для 'shared_from_this' для работы там __must__ будет' shared_ptr', уже владеющим объектом, поскольку слабые ссылки будут угрожать объекту как недействительным в противном случае. Здесь возникает ограничение на конструктор: он владеет 'shared_ptr', который правильно устанавливает слабую ссылку и не может выполнять свою работу до тех пор, пока объект не будет полностью построен. –

+0

Спасибо вам за ваши ответы. Я попытался вызвать функцию 'start' из' main' -I включил код в вопрос, но он все равно дает мне ту же ошибку. Я видел с отладчиком, что он дает мне ошибку в точной точке, в которой я называю 'shared_from_this' в функции запуска. Почему это? – MikelAlejoBR

+0

@StrikeTeam Поскольку 'w' не является' shared_ptr'. – Barry