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を参照として返し、それを参照で渡すことができることはわかっていますが、_addressesへの参照よりも先にCustomerインスタンスがスコープ外になり、「ぶら下がり参照」が発生する可能性があるため、問題が発生する可能性があります。私は検索からそれだけ多くを見つけました。私が見つけられなかったのは、代わりに何をすべきかということでした。明らかに、この種のことを行うための標準的な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は本当に別のクラスに属するべきですか?Customerクラスに属しているように見えますか?

3.さらなる機能強化、forループの代わりにQlistアルゴリズムを使用してアドレスを見つけることができますか?

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

setAsShippingの戻り型をとして保持する代わりに、QListオブジェクトのコピーを返すことを試みることができるかもしれませんvoid

于 2012-11-28T04:10:04.717 に答える
-1

C#プロパティと同等のものを使用するには、テンプレート(QSharedPointer)のパラメーターを変更する必要があります。

class Customer : {
  public:
     QList<QSharedPointer<Address> > _addresses;
};

QSharedPointerは、煩わしい参照カウントポインタではありません(これにより、メモリ管理が簡素化されます)。このようにして、QList要素を変更できます(これが必要です)が、このQListの内容を変更(要素の追加/削除/置換)することはできません。それでも、アドレスの通常のゲッター(参照ではなく値を返す)があります。 。

したがって、問題のあるコードは次のように機能します。

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を使用できます(参照カウントの侵入型ポインター-この場合、AddressQSharedDataを拡張する必要があります)。

于 2012-11-28T09:30:43.397 に答える