通常,很多代码除了获取/设置类成员之外什么都不做。为此,我实现了一个简单的容器类,以使getter和setter相关联 到一个“领域”。乍一看,这看起来很不错,导致代码少得多。这就是容器类的样子:
Member.h
#include <functional>
template <class T>
class Member
{
public:
T data;
using Getter_t = std::function<T(void)>;
using Setter_t = std::function<void(T)>;
using Notify_t = std::function<void(void)>;
Setter_t m_setterFunc;
Getter_t m_getterFunc;
Notify_t m_notifyFunc;
Member()
{
this->m_getterFunc = [=] (void) -> T { return this->data; };
this->m_setterFunc = [=] (T data) -> void { this->data = data; };
this->m_notifyFunc = [] (void) -> void { };
}
auto get() -> T { return this->m_getterFunc(); }
auto set(T data) -> void { this->m_setterFunc(data); this->m_notifyFunc(); }
auto getter(Getter_t func) -> Member& { this->m_getterFunc = func; return *this; }
auto setter(Setter_t func) -> Member& { this->m_setterFunc = func; return *this; }
auto notify(Notify_t func) -> Member& { this->m_notifyFunc = func; return *this; }
~Member() { }
};
我知道有些事情还不完美,但现在还可以。接下来的几行显示了如何定义Member
个实例以及访问底层数据的简单方便的方法。 get
,set
和notify
函数可以替换为lambdas或函数指针来覆盖自定义行为。
的main.cpp
#include <iostream>
#include "Member.h"
class MyClass
{
public:
Member<int> foo;
Member<std::string> bar;
void barChanged() { std::cout << "bar changed\n"; }
};
auto main(int argc, const char * argv[]) -> int
{
MyClass instance;
instance.foo.notify([] () -> void { std::cout << "foo changed\n"; });
instance.bar.notify(std::bind(&MyClass::barChanged, instance));
instance.foo.set(10);
instance.bar.set("some string");
std::cout << instance.foo.get() << " " << instance.bar.get() << std::endl;
return 0;
}
现在的问题是Q_PROPERTY
宏需要READ
和WRITE
访问器的函数名称,我回到我开始的地方:我必须编写get和set函数对于每个属性明确。正是我想要避免的。
class MyOtherClass : public QObject
{
Q_OBJECT
Q_PROPERTY(bool flag READ getFlag WRITE setFlag NOTIFY flagChanged);
public:
Member<bool> m_flag;
auto getFlag() -> bool { return m_flag.get(); }
auto setFlag(bool flag) -> void { this->m_flag.set(flag); }
};
是否可以直接使用现有的m_flag.get
和m_flag.set
函数?我尝试了一些显而易见的事情,但是他们要么被moc拒绝,要么导致代码过多。
如下所述,MEMBER
关键字可以在不指定get和set函数的情况下拥有属性。但是,私人成员只能通过他们的名字(this->property("myPropertyName")
)访问,而且没有办法实现“普通”获取和设置。
更明确地说:动机不仅仅是避免编写get和set函数,而是试图实现一个灵活的成员系统
唯一缺失的部分是Q_PROPERTY
READ
/ WRITE
访问者与Member
类的get / set方法之间的桥梁。
感谢您的帮助!
答案 0 :(得分:7)
我不认为可以在不编写包装器的情况下将READ
或WRITE
属性方法重定向到其他内部或外部对象,但如果您的getter和setter除了返回或设置数据:至少在最新的Qt版本中存在MEMBER
变量关联。
来自Qt Doc:
Q_PROPERTY(type name
(READ getFunction [WRITE setFunction] |
MEMBER memberName [(READ getFunction | WRITE setFunction)])
[RESET resetFunction]
[NOTIFY notifySignal]
[REVISION int]
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
[FINAL])
如果没有MEMBER变量,则需要READ访问器功能 指定。这是为了阅读房产价值。理想情况下,const 函数用于此目的,它必须返回 属性的类型或对该类型的const引用。例如。, QWidget :: focus是一个只读属性,具有READ函数, QWidget的:: hasFocus()。
WRITE访问器功能是可选的。它用于设置属性 值。它必须返回void并且必须只接受一个参数 属性的类型或指向该类型的指针或引用。例如。, QWidget :: enabled具有WRITE函数QWidget :: setEnabled()。 只读属性不需要WRITE函数。例如,QWidget :: focus 没有WRITE功能。
如果没有READ访问器功能,则需要MEMBER变量关联 已指定。这个使给定的成员变量可读 可写,无需创建READ和WRITE访问器 功能即可。仍然可以使用READ或WRITE访问器功能 除了MEMBER变量关联(但不是两者),如果需要 控制变量访问。
使用MEMBER
您不需要编写getter和setter。