Qt窗口切换--原始指针 VS Boos方式

来源:互联网 发布:小程序模板源码下载 编辑:程序博客网 时间:2024/05/12 07:54

这两天在做Qt多窗口切换测试,上一篇博客,也说明了一种切换的方式,不过上一种有较强耦合性,为什么呢,就是在主窗口的.h或.cpp里面必须包含子窗口的头文件,才行。

那么想要做低耦合,就是A窗口和B窗口不互相包含,怎么办呢?

方法一:我首先,想到的是在A窗口类中定义一个B窗口的基指针以及获取B窗口指针的函数,为啥用基指针呢,原因就是不想再去包含B窗口头文件,因为AB两个窗口都继承自QWidget,所以我可以AB两个类都定义一个存对方窗口指针的变量和获取对方窗口的函数。那么在主函数中我定义两个变量后,再相互传一下指针,不就可以解决互访问题了!!

widget(主窗口)

// widget.h

#ifndef WIDGET_H#define WIDGET_H

#include <QWidget>namespace Ui {class Widget;}

class Widget : public QWidget{    Q_OBJECT    public:    explicit Widget(QWidget *parent = 0);    ~Widget();     void GetChildWinPtr(QWidget *window);//获取子窗口指针函数private slots:    void on_pushButton_clicked();

private:    Ui::Widget *ui;   QWidget *child; //存储子窗口指针};

#endif // WIDGET_H//widget.cpp

#include "widget.h"#include "ui_widget.h"#include <QDebug>

Widget::Widget(QWidget *parent) :    QWidget(parent),    ui(new Ui::Widget){    ui->setupUi(this);    setWindowTitle("Main Window");    qDebug() << "construct main";}

Widget::~Widget(){    delete ui;    qDebug() << "delete main";}void Widget::GetChildWinPtr(QWidget* window){    child = window;}void Widget::on_pushButton_clicked(){    this->close();    child->show();

}

child(子窗口)

//child.h

#ifndef CHILD_H#define CHILD_H

#include <QWidget>#include <boost/shared_ptr.hpp>

namespace Ui {class Child;}

class Child : public QWidget{    Q_OBJECT    public:    explicit Child(QWidget *parent = 0);    ~Child();   void GetMainWinPtr(QWidget* window);//获取主窗口指针函数    void GetMainWinPtr(boost::shared_ptr<QWidget> window);private slots:    void on_pushButton_clicked();

private:    Ui::Child *ui;   QWidget *main;//主窗口指针};

#endif // CHILD_H//child.cpp

#include "child.h"#include "ui_child.h"#include <QDebug>

Child::Child(QWidget *parent) :    QWidget(parent),    ui(new Ui::Child){    ui->setupUi(this);    setWindowTitle("Child Window");    qDebug() <<"construct child";}

Child::~Child(){    delete ui;    qDebug() <<"delete child";}

void Child::GetMainWinPtr(QWidget* window){    main = window;}void Child::on_pushButton_clicked(){    this->close();    main->show();}

 

main.cpp

#include <QtGui/QApplication>#include "widget.h"#include "child.h"#include <QDebug>#include <boost/shared_ptr.hpp>#include <boost/smart_cast.hpp>

int main(int argc, char *argv[]){    QApplication a(argc, argv);

Widget w;

Child cld;

w.GetChildWinPtr(&cld);

cld.GetMainWinPtr(&w);

w.show();

//也可以用new的方式来建立两个窗口,不过会造成内存泄漏    return a.exec();}

这样可以解决问题,但注意,主窗口和子窗口不能成父子关系!!!!!!!

方法二:boost::shared_ptr方式

child

//child.h

#ifndef CHILD_H#define CHILD_H

#include <QWidget>#include <boost/shared_ptr.hpp>

namespace Ui {class Child;}

class Child : public QWidget{    Q_OBJECT    public:    explicit Child(QWidget *parent = 0);    ~Child();    //void GetMainWinPtr(QWidget *window);    void GetMainWinPtr(boost::shared_ptr<QWidget> window);private slots:    void on_pushButton_clicked();

private:    Ui::Child *ui;    //QWidget * main;    boost::shared_ptr<QWidget> main;};

#endif // CHILD_H //child.cpp

#include "child.h"#include "ui_child.h"#include <QDebug>

Child::Child(QWidget *parent) :    QWidget(parent),    ui(new Ui::Child){    ui->setupUi(this);    qDebug()<< "construct a child";}

Child::~Child(){    delete ui;    qDebug()<< "delete a child";}

void Child::GetMainWinPtr(boost::shared_ptr<QWidget> window){    main = window;}/*void Child::GetMainWinPtr(QWidget *window){    main = window;}*/void Child::on_pushButton_clicked(){    close();    main->show();}

widget

//widget.h

#ifndef WIDGET_H#define WIDGET_H

#include <QWidget>#include <boost/shared_ptr.hpp>namespace Ui {class Widget;}

class Widget : public QWidget{    Q_OBJECT    public:    explicit Widget(QWidget *parent = 0);    ~Widget();    void GetChildWinPtr(QWidget * window);    void GetChildWinPtr(boost::shared_ptr<QWidget> window);private slots:    void on_pushButton_clicked();

private:    Ui::Widget *ui;    //QWidget * child;    boost::shared_ptr<QWidget> child;};

#endif // WIDGET_H

//widget.cpp

#include "widget.h"#include "ui_widget.h"#include <QDebug>

Widget::Widget(QWidget *parent) :    QWidget(parent),    ui(new Ui::Widget){    ui->setupUi(this);    qDebug()<< "construct a main";}

Widget::~Widget(){    delete ui;    qDebug()<< "delete a main";}/*void Widget::GetChildWinPtr(QWidget *window){    child = window;}*/

void Widget::GetChildWinPtr(boost::shared_ptr<QWidget> window){    child = window;}

void Widget::on_pushButton_clicked(){    close();    child->show();}

main.cpp

#include "widget.h"#include <QApplication>#include "child.h"#include <boost/shared_ptr.hpp>

int main(int argc, char *argv[]){    QApplication a(argc, argv);    /*    Widget w;    Child cld;    w.GetChildWinPtr(&cld);    cld.GetMainWinPtr(&w);    w.show();    */    boost::shared_ptr<Widget> m_main(new Widget);    boost::shared_ptr<Child> m_child(new Child);    m_main->GetChildWinPtr(boost::dynamic_pointer_cast<QWidget>(m_child));    m_child->GetMainWinPtr(boost::dynamic_pointer_cast<QWidget>(m_main));    m_main->show();    a.exec();    m_main->GetChildWinPtr(boost::shared_ptr<QWidget>());    m_child->GetMainWinPtr(boost::shared_ptr<QWidget>());    return 0;}

注意,main函数后半节,m_main->GetChildWinPtr(boost::shared_ptr<QWidget>());必须要再传一个空shared_ptr进去,因为child和widget类中分别还有个shared_ptr变量,用于保存两个窗口指针,虽然当主函数执行完后,主函数中保存两个窗口指针的shared_ptr变量,释放了,但引用计数只是减了1,由于child和widget类中还有shared_ptr,没有被 释放,所以child和widget指针不会释放。因此,在这里传个boost::shared_ptr<QWidget>()空的shared_ptr给child和widget类中的指针,从而使它们释放掉两个child和widget指针。因为赋空操作,引用计数将直接变为0。


 

方法三:boost::function+bind形式,这种方法不用传指针

child

//child.h

#ifndef CHILD_H#define CHILD_H

#include <QWidget>//#include <boost/shared_ptr.hpp>#include <boost/function.hpp>

namespace Ui {class Child;}

class Child : public QWidget{    Q_OBJECT    Q_OBJECTpublic:    explicit Child(QWidget *parent = 0);    ~Child();    //void GetMainWinPtr(QWidget *window);    //void GetMainWinPtr(boost::shared_ptr<QWidget> window);    void SetOnMainWinShow(boost::function<void()> m_main);private slots:    void on_pushButton_clicked();private:    class impl;    impl * m_impl;private:    Ui::Child *ui;    //QWidget * main;    //boost::shared_ptr<QWidget> main;};

#endif // CHILD_H

//child.cpp

#include "child.h"#include "ui_child.h"#include <QDebug>

class Child::impl{public:    boost::function<void()> m_main_show;};Child::Child(QWidget *parent) :    QWidget(parent),    ui(new Ui::Child){    ui->setupUi(this);    m_impl = new impl();    qDebug()<< "construct a child";

}

Child::~Child(){    delete ui;    qDebug()<< "delete a child";}

void Child::SetOnMainWinShow(boost::function<void ()> m_main){    m_impl->m_main_show = m_main;}

/*void Child::GetMainWinPtr(QWidget *window){    main = window;}*/void Child::on_pushButton_clicked(){    close();    //main->show();    if(m_impl->m_main_show)        m_impl->m_main_show();}

widget

//widget.h

#ifndef WIDGET_H#define WIDGET_H

#include <QWidget>#include <boost/shared_ptr.hpp>#include <boost/function.hpp>

namespace Ui {class Widget;}

class Widget : public QWidget{    Q_OBJECT    public:    explicit Widget(QWidget *parent = 0);    ~Widget();    void GetChildWinPtr(QWidget * window);    void GetChildWinPtr(boost::shared_ptr<QWidget> window);    void SetOnChildWinPtr(boost::function<void()> m_child);private slots:    void on_pushButton_clicked();

private:    Ui::Widget *ui;    //QWidget * child;    //boost::shared_ptr<QWidget> child;private:    class impl;    impl *m_impl;};

#endif // WIDGET_H//widget.cpp

#include "widget.h"#include "ui_widget.h"#include <QDebug>class Widget::impl{public:    boost::function<void()> m_child_show;};Widget::Widget(QWidget *parent) :    QWidget(parent),    ui(new Ui::Widget){    ui->setupUi(this);    m_impl = new impl();    qDebug()<< "construct a main";}

Widget::~Widget(){    delete ui;    qDebug()<< "delete a main";}/*void Widget::GetChildWinPtr(QWidget *window){    child = window;}*/

 

void Widget::SetOnChildWinPtr(boost::function<void ()> m_child){    m_impl->m_child_show = m_child;}

void Widget::on_pushButton_clicked(){    close();    //child->show();    if(m_impl->m_child_show)        m_impl->m_child_show();}

main.cpp

#include "widget.h"#include <QApplication>#include "child.h"#include <boost/shared_ptr.hpp>#include <boost/bind.hpp>#include <QDebug>int main(int argc, char *argv[]){    QApplication a(argc, argv);    /*    Widget w;    Child cld;    w.GetChildWinPtr(&cld);    cld.GetMainWinPtr(&w);    w.show();w.show();    */    /*    boost::shared_ptr<Widget> m_main(new Widget);    boost::shared_ptr<Child> m_child(new Child);    m_main->GetChildWinPtr(boost::dynamic_pointer_cast<QWidget>(m_child));    m_child->GetMainWinPtr(boost::dynamic_pointer_cast<QWidget>(m_main));    m_main->show();    a.exec();    m_main->GetChildWinPtr(boost::shared_ptr<QWidget>());    m_child->GetMainWinPtr(boost::shared_ptr<QWidget>());    */    boost::shared_ptr<Widget> m_main(new Widget);    boost::shared_ptr<Child> m_child(new Child);    m_main->SetOnChildWinShow(boost::bind(&Child::show,m_child));    m_child->SetOnMainWinShow(boost::bind(&Widget::show,m_main));//bind会返回一个函数对象,里面保存一个对象拷贝,这个对象,再赋值给最底层的function,所以最底层的function里面存放了,shared_ptr的拷贝,所以应用计数为2,不会析构

        m_main->show();    qDebug() << m_main.use_count();    a.exec();    m_main->SetOnChildWinShow(boost::function<void()>());//手动赋值,function对象为空,从而使其释放掉里面保存的shared_ptr拷贝    m_child->SetOnMainWinShow(boost::function<void()>());    return 0;}