在C ++中的两个类之间共享一个实例(QList)

时间:2012-11-28 03:52:03

标签: c# c++ qt

从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可以修改地址列表?

3 个答案:

答案 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)。