从C#到Qt我无法理解如何正确翻译以下常用习语(C#):
class Customer {
public property List<Address> Addresses { get; }
}
class AnotherClass {
public void SetAsShipping(List<Address> addresses) {
foreach(var address in addresses)
if (address.IsMatch(_shipping))
address.IsShipping = true; // This is the important part
}
}
var cust = new Customer();
var another = new AnotherClass();
another.SetAsShipping(cust.Addresses);
我有以下C ++:
class Customer {
public:
QList<Address> addresses() const { return _addresses; }
private:
QList<Address> _addresses;
};
class AnotherClass {
public:
void setAsShipping(QList<Address> addresses);
};
AnotherClass::setAsShipping(QList<Address> addresses) {
QList<Address>::iterator address;
for (address = addresses->begin(); address != addresses->end(); ++address)
if (address->isMatch(_shipping))
address->setIsShipping(true); // This is modifying a copy :(
}
Customer cust;
AnotherClass another;
another.setAsShipping(cust.addresses());
我知道我可以将_addresses作为引用返回,然后通过引用传递它,但显然这可能会导致问题,因为我的Customer实例在引用_addresses之前可能超出范围,这将导致“悬空引用”。我从搜索中发现了很多。我没有找到的是人们应该做的事情。显然有一种标准的C ++方式来做这种事情,但是我的大脑在托管代码模式中如此困难,以至于它不会向我跳出来。我应该如何编写此代码,以便AnotherClass可以修改地址列表?
答案 0 :(得分:1)
在你的C#Customer类中,地址只是公共属性,你也可以在C ++中实现,但它显然不是一个好的设计。
class Customer {
public:
QList<Address> _addresses;
};
AnotherClass::setAsShipping(QList<Address>& addresses) {
for (QList<Address>::iterator address = addresses->begin();
address != addresses->end(); ++address)
{
if (address->isMatch(_shipping)) {
address->setIsShipping(true); // Now modify the real object
}
}
}
为了更好地做到这一点,让我们重新考虑您的C#设计。
1.为什么List<Address> Addresses
公开?
2.Sh.SAsAsShipping真的属于另一个类吗?看起来它属于Customer类?
3.进一步增强,可以使用Qlist算法来查找地址而不是for循环吗?
class Customer
{
public:
void setAsShipping(const Address& address)
{
for (QList<Address>::iterator address = addresses->begin();
address != addresses->end(); ++address)
{
if (address->isMatch(_shipping)) {
address->setIsShipping(true); // Now modify the real object
}
}
}
private:
QList<Address> _addresses;
};
customer cust;
AnotherClass another;
cust.setAsShipping(another.address());
现在还有悬而未决的参考问题吗?
答案 1 :(得分:0)
可能您可以尝试返回QList对象副本,而不是将setAsShipping
的返回类型保持为void
。
答案 2 :(得分:-1)
要拥有等效的C#属性,您必须更改模板的参数(QSharedPointer):
class Customer : {
public:
QList<QSharedPointer<Address> > _addresses;
};
QSharedPointer是无介入的引用计数指针(这将简化内存管理)。 这样你可以对QList元素进行修改(这是你需要的),但是你无法改变这个QList的内容(添加/删除/替换元素),你仍然可以获得正常的getter(返回值而不是引用)
所以你有问题的代码会像这样工作:
AnotherClass::setAsShipping(const QList<Address> addresses) {
// here you have a copy of QList - it is copy on write pattern
// so adding const will prevent from creating a copy of QList
Q_FOREACH (QSharedPointer<Address> address, addresses)
if (address->isMatch(_shipping))
address->setIsShipping(true); // This will modify original value
}
您可以使用QSharedDataPointer(引用计数侵入式指针 - 在这种情况下Address
必须扩展QSharedData)。