sco*_*nov 6 c++ lambda qt c++11 qt5
我担心在将来升级Qt 5.9下开发的小部件库是可能的,而不必重新编译已经使用它的代码.当然,我已经开始使用PImpl成语和它在这里和这里描述的Qt版本.
然而,在尝试调整我的代码时,我提出了这样的想法,即不是添加新的数据成员并将它们移动到单独的私有类,我可以使用Qt的信号/槽机制和lambda函数,并且只有局部变量.让我们用以下示例说明这个想法:
变式A:
class Foo : public QWidget
{
Q_OBJECT
public:
explicit Foo(QWidget *parent = nullptr);
private:
// A bunch of data members
QPushButton *m_button;
QLineEdit *m_lineEdit;
QCheckBox *m_checkBox;
QString m_str;
private slots:
void on_pushButtonClicked();
void on_checkBoxStateChanged(int state);
};
Foo::Foo(QWidget *parent) :
QWidget(parent),
m_button(new QPushButton("Click me", this));
m_lineEdit(new QLineEdit(this)),
m_checkBox(new QCheckBox(this)),
m_str("Initial text")
{
connect(button, &QPushButton::clicked, this, &Foo::on_pushButtonClicked);
connect(checkBox, &QCheckBox::stateChanged, this, &Foo::on_checkBoxStateChanged);
}
Foo::on_pushButtonClicked()
{
m_str = m_lineEdit->text();
m_lineEdit->setDisabled(m_checkBox->isChecked());
}
Foo::on_checkBoxStateChanged(int state)
{
m_button->setText(state == Qt::Checked ? m_str : "Click me")
}
Run Code Online (Sandbox Code Playgroud)
变式B:
class Foo : public QWidget
{
Q_OBJECT
public:
explicit Foo(QWidget *parent = nullptr);
};
Foo::Foo(QWidget *parent) : QWidget(parent)
{
QPushButton *button = new QPushButton("Click me", this);
QLineEdit *lineEdit = new QLineEdit(this);
QCheckBox *checkBox = new QCheckBox(this);
QString str("Initial text");
connect(button, &QPushButton::clicked, [=](){
str = lineEdit->text();
lineEdit->setDisabled(checkBox->isChecked());
});
connect(checkBox, &QCheckBox::stateChanged, [=](int state){
button->setText(state == Qt::Checked ? str : "Click me")
});
}
Run Code Online (Sandbox Code Playgroud)
因此,对于Variant B - 除了更紧凑外,它不包含任何类数据成员,因此没有要隐藏的变量,因此不需要D指针.如果将来构造函数重新实现了以相同信号/槽方式使用的其他局部变量,那么二进制兼容性仍然可以保证(或者是吗?).我是否认为这会起作用或者这样的方法根本不会起作用?
注:有关使用Lambda表达式为Qt的插槽检查由@Igor Tandetnik评论更多信息在这里.
我提出了这个想法,而不是添加新的数据成员并将它们移动到单独的私有类 [...]
这是错误的思考方式。该接口没有数据成员。无论您有哪些成员,都可以直接进入 PIMPL。您不会“移动”任何东西,也不会将它们添加到错误的位置。
此外,与父对象具有相同生命周期的成员的堆分配是一种过早的悲观。按值将它们存储在 PIMPL 中。
[...] 我可以将 Qt 的信号/槽机制与 lambda 函数一起使用,并且只有局部变量
当你需要存储比QObject孩子更多的东西而不滥用财产系统时,这将不起作用。
这不是一个灵活的方法,而且正确地做到这一点并不难。Qt 建立了所有必要的模式。请参阅此问题了解一些详细信息。
您不打算派生的类不需要单独的Class_p.h标头。您可以将ClassPrivate定义添加到文件本身的开头Class.cpp。
// Foo.h
#include <QWidget>
class FooPrivate;
class Foo : public QWidget {
Q_OBJECT
Q_DECLARE_PRIVATE(Foo)
QScopedPointer<FooPrivate> const d_ptr;
public:
explicit Foo(QWidget *parent = {});
~Foo();
protected:
Foo(FooPrivate &, QWidget *parent = {}); // for expansion
};
Run Code Online (Sandbox Code Playgroud)
// Bar.h
#include "Foo.h"
class BarPrivate;
class Bar : public Foo {
Q_OBJECT
Q_DECLARE_PRIVATE(Bar)
Q_PROPERTY(int data READ data)
public:
explicit Bar(QWidget *parent = {});
~Bar();
int data() const;
protected:
Bar(BarPrivate &, QWidget *parent = {}); // for expansion
};
Run Code Online (Sandbox Code Playgroud)
// Foo_p.h
#include "Foo.h"
class FooPrivate {
Q_DECLARE_PUBLIC(Foo)
Q_DISABLE_COPY(Foo) // usually desired
Foo * const q_ptr;
public:
QVBoxLayout m_layout{q_ptr};
QPushButton m_button{q_ptr->tr("Hello!")};
QLineEdit m_lineEdit;
QCheckBox m_checkBox{q_ptr->tr("Active")};
void on_pushButtonClicked();
void on_checkBoxStateChanged(int state);
explicit FooPrivate(Foo *);
virtual ~FooPrivate() {} // we're meant to be derived from!
};
Run Code Online (Sandbox Code Playgroud)
// Bar_p.h
#include "Foo_p.h"
#include "Bar.h"
class BarPrivate : public FooPrivate {
Q_DECLARE_PUBLIC(Bar)
public:
int m_data = 44;
explicit BarPrivate(Bar *);
};
Run Code Online (Sandbox Code Playgroud)
// Foo.cpp
#include "Foo_p.h"
Foo::Foo(QWidget * parent) :
Foo(*new FooPrivate(this), parent)
{}
Foo::Foo(FooPrivate & d_ptr, QWidget * parent) :
QWidget(parent),
d_ptr(d_ptr)
{}
Foo::~Foo() {}
FooPrivate::FooPrivate(Foo * q_ptr) :
q_ptr(q_ptr)
{
m_layout.addWidget(&m_button);
m_layout.addWidget(&m_lineEdit);
m_layout.addWidget(&m_checkBox);
connect(&m_button, &QPushButton::clicked, [=]{ on_pushButtonClicked(); });
connect(&m_checkBox, &QCheckBox::stateChanged, [=](int s){ on_checkBoxStateChanged(s); });
}
Run Code Online (Sandbox Code Playgroud)
// Bar.cpp
#include "Bar_p.h"
Bar::Bar(QWidget * parnet) :
Bar(*new BarPrivate(this), parent)
{}
Bar::Bar(BarPrivate & d_ptr, QWidget * parent) :
Foo(d_ptr, parent)
{}
Bar::~Bar() {}
BarPrivate::BarPrivate(Bar * q_ptr) :
FooPrivate(q_ptr)
{}
int Bar::data() const {
Q_D(const Bar);
return d->m_data;
}
Run Code Online (Sandbox Code Playgroud)