当然没有这样的成员,因为您自己已经说过吸气剂被称为getMyProp
,设置器被称为setMyProp
。成员的定义称为MyProp
完全取决于你。下面,我将展示如何定义此类成员。
我们还应该注意到,在 Qt 中,习惯上不要在 getter 前面加上get
,但只需以属性命名即可。这样你就有了
Q_PROPERTY(int foo READ foo WRITE setFoo)
// rather than
Q_PROPERTY)int foo READ getFoo WRITE setFoo)
可能的解决方案包括:
(1) 直接访问属性的数据成员 - 这会破坏属性系统授予的封装性,并且不建议这样做。
class Direct : public QObject {
Q_OBJECT
Q_PROPERTY(int prop MEMBER prop)
public:
int prop;
};
Direct d;
d.prop = 3;
Q_ASSERT(d.property("prop").toInt() == 3);
最后一行有效是因为moc生成简单的 getter 和 setter 代码,然后可以通过元对象系统访问这些代码。此代码嵌入在元数据实现中,不会导致任何方法添加到类本身。
(2) 有一个返回引用的 getter。当 getter 和 setter 很简单时,这是最简单、低开销的方法。
class GetSet : public QObject {
Q_OBJECT
Q_PROPERTY(int prop READ prop WRITE setProp)
int m_prop;
public:
int & prop() { return m_prop; }
int prop() const { return m_prop; }
void setProp(int prop) { m_prop = prop; }
};
GetSet gs;
gs.prop() = 3; // assignment syntax through "getter"
Q_ASSERT(gs.property("prop").toInt() == 3);
gs.setProp(4); // setter syntax
Q_ASSERT(gs.property("prop").toInt() == 4);
(3) 公开充当财产代理的成员。这允许在没有调用语法的情况下使用代理:obj.prop
代替obj.prop()
.
(3a) 我们可以使用 Qt 属性系统来访问命名属性。这QMetaProperty
充当缓存以避免每次属性访问时重复名称查找。 AQVariant
对每个属性访问执行转换。
template <typename B, typename T> class PProxy {
Q_DISABLE_COPY(PProxy)
B * obj;
QMetaProperty prop;
public:
PProxy(B & o, const char * p) : obj(&o),
prop(o.metaObject()->property(o.metaObject()->indexOfProperty(p))) {}
T operator=(const T & val) { prop.write(obj, val); return val; }
T operator=(T && val) { prop.write(obj, val); return val; }
operator T() const { return prop.read(obj).value<T>(); }
};
class ViaPProxy : public QObject {
Q_OBJECT
Q_PROPERTY(int prop READ getProp WRITE setProp)
int m_prop;
public:
PProxy<Direct, int> prop;
ViaPProxy() : prop(*this, "prop") {}
int getProp() const { return m_prop; }
void setProp(int val) { m_prop = val; }
}
ViaPProxy vpp;
vpp.prop = 3; // invokes the setter through a proxy
Q_ASSERT(vpp.prop == 3);
(3b) 而不是通过 Qt 属性系统QVariant
转换时,代理可以直接使用 getter 和 setter。这比 (3a) 的开销更低,但要求存在 getter 和可选的 setter。
template <typename B, typename T,
T (B::*get)() const, void (B::*set)(T) = 0> class DProxy {
Q_DISABLE_COPY(DProxy)
B & obj;
public:
DProxy(B & o) : obj(o) {}
T operator=(const T & val) { (obj.*set)(val); return val; }
T operator=(T && val) { (obj.*set)(std::forward<T>(val)); return val; }
operator T() const { return (obj.*get)(); }
};
class ViaDProxy : public QObject {
Q_OBJECT
Q_PROPERTY(int prop READ getProp WRITE setProp)
int m_prop;
public:
DProxy<Direct, int, &ViaDProxy::get, &ViaDProxy::set> prop;
ViaDProxy() : prop(*this) {}
int getProp() const { return m_prop; }
void setProp(int val) { m_prop = val; }
}
ViaDProxy vdp;
vdp.prop = 3; // invokes the setter through a proxy
Q_ASSERT(vdp.prop == 3);