0

ここに設計上の問題があると思います。助けていただければ幸いです。

基本的なアルゴリズムを表す Base クラスがあります。

class BaseAlgo: public Algo<double>
{
public:

/// data structures
// ...
// 
 struct Item {
    double profit;
    double weight;
    double xjSolution;
 };

 typedef std::pair<double, std::vector<Item>::iterator> ScaledItem;

protected:

 std::vector<Item> & items_;
 boost::ptr_vector<ScaledItem> largeItems_;
}

BaseAlgo にはいくつかの機能があり、仮想的なものもあればそうでないものもあります。

私が持っている派生クラスとして

class DerivedAlgo: public BaseAlgo
{
public:

/// enhanced data structures
// ...
// 

 struct DerivedScaledItem : ScaledItem {
    int additional;
 };
 }

DerivedAlgo でオーバーロードする仮想関数では、DerivedScaledItem の追加パラメーターにアクセスする必要がありますが、これはポリモーフィズムの本来の目的ではありません。どういうわけかそれは可能ですか、それとも別の設計アプローチを提案していますか? 私は完全に立ち往生しているので、現時点では何でも受け入れることができます。

現在、BaseAlgo の largeItems_ メンバー ptr_vector は、ScaledItems を (内部的にポインターとして) 保持しています。私は、これを次のように使用できると思いました:

// in DerivedAlgo

void someMethod(std::vector<Item>::iterator someiterator){
   DerivedScaledItem doubledItem = {};

   doubledItem.first = 4.5;
   doubledItem.second = someiterator;
   doubledItem.additional= 2;
   largeItems_.push_back(new UnboundedScaledItem(doubledItem));
   boost::ptr_vector<DerivedScaledItem>::iterator it = largeItems_.begin();
   std::cout << "added large item " << *it << std::endl;
}

追加したばかりのオブジェクトをカウントすると、追加は 2 に設定されます。しかし、その後、largeItems_ のゲッターを呼び出すと、追加フィールドは 0 に戻され、ScaledItem で認識されている 2 つのフィールドのみが設定されます。

// in BaseAlgo
const boost::ptr_vector<ScaledItem>& getLargeItems() const
{
    return largeItems_;
}

// from my test.cpp
DerivedAlgo obj;
// ... define someiterator
obj.someMethod(someiterator);
boost::ptr_vector<BaseAlgo::ScaledItem> largeItems = knapsack.getLargeItems();
boost::ptr_vector<DerivedAlgo::DerivedScaledItem>::iterator it = largeItems.begin();
std::cout << "read large item " << *it << std::endl;
4

1 に答える 1

1

ここで説明されているように、ptr_vector-s要素を複製する方法をブーストに伝えていなかったと思います: http://www.boost.org/doc/libs/1_54_0/libs/ptr_container/doc/tutorial.html#cloneability

したがって、ベクトルのコピーを作成するこの行では (largeItems参照として宣言することでこれを回避できます)、それらは のコンストラクターを介してコピーされScaledItem、追加のメンバーが失われます。

boost::ptr_vector<BaseAlgo::ScaledItem> largeItems = knapsack.getLargeItems();

別のデザインに関するご質問について:

  • ベクター要素の型をテンプレート パラメーターとして基本クラスに渡すことができます。
  • ベクターを派生クラスに移動し、基本クラスの単一要素にアクセスするための (仮想、抽象) 関数のみを提供できます。基本クラスでも要素を作成できる場合は、何らかのファクトリ メソッドが必要になる場合があります。ベクター内の要素の基本的な種類が必要ないためです。
于 2013-10-17T23:37:15.417 に答える