2

从 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 修改?

4

3 回答 3

1

在您的 C# Customer 类中,Addresses 只是公共属性,您也可以在 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.SetAsShipping真的应该属于Another类吗?看起来它属于客户类?

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()); 

现在还有悬而未决的参考问题吗?

于 2012-11-28T04:36:49.480 回答
0

May be you can try returning the QList object copy instead of keeping the return type of setAsShipping as void.

于 2012-11-28T04:10:04.717 回答
-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)。

于 2012-11-28T09:30:43.397 回答