0

次のテストがあります。

TestGet(): _interface(), _db(_interface)
{
    _interface.get = mockGet;
}

このクラスをテストするときに使用されます。

class DB: public IDB
{
public:
   explicit DB(Interface_T& interface):
     _interface(interface)
   {
   }

   ...

private:
   Interface_T _interface;
};

Interface_T は、構造体に実装され、C API から渡された C インターフェイスです。DB クラスを C インターフェイスのラッパーとして使用したいと考えています。

ただし、DB はインターフェイス オブジェクトをそのメンバー _interface にコピーすることに注意してください。したがって、次の行:

_interface.get = mockGet;

これは、テスト クラスを作成したときの意図でしたが、DB オブジェクトの観点からは効果がありません。このエラーを修正するには、TestGet() をどのように書き直しますか? DB クラスのクライアントに、渡された値をコピーすることをどのように提示しますか?

4

4 に答える 4

1

によって使用されるオブジェクトTestGetにメンバーを設定する意図があると仮定すると、次のことができます。Interface_TDB

A. の構築を延期するDB:

TestGet(): _interface(), _db(NULL)
{
    _interface.get = mockGet;

    // Using a raw pointer here for minimalism, but in practice
    // you should prefer a smart pointer type.
    _db = new DB(_interface);
}

B.Interface_Tクラスを制御できる場合は、直接初期化するコンストラクターを追加できますInterface_T::get。次に、次のことができます。

TestGet(): _interface(mockGet), _db(_interface)
{
}

C. クラスを制御できる場合DBは、提供されたクラスの所有権を共有するようにクラスを変更したりInterface_T(例: を介してboost::shared_ptr)、B のようにコンストラクターを追加したり、内部Interface_Tメンバーにアクセサーを追加したりできます。

于 2012-10-02T09:26:57.123 に答える
1

そのため、db get が構築されるまでにインターフェイスを正しくする必要があります。まあ、それは簡単です。関数で適切なインターフェイスを作成し、結果をコンストラクターに渡すだけです。

Interface_T makeMockInterface()
{
    Interface_T interface;
    // I presume you will first use the C API to initialize it and than
    interface.get = mockGet;
}

TestGet() : _db(makeMockInterface())
{
}

Interface_Tからの値によって返されますmakeMockInterfaceが、基礎となるマシン コードは実際にはオブジェクトを呼び出し元が提供する空間にコピーして返すため、ほとんどのコンパイラは実際にはコピーを省略し、呼び出し元が提供する空間にオブジェクトを直接構築します (これは標準で明示的に許可されています)。 )。

TestGet クラスには個別の _interface メンバーを含める必要はありません。これは、_db にそれが含まれており、とにかく共有されないため、意味がありません。

編集:コンストラクターは非 const 参照を使用DBしますが、オブジェクトをコピーするだけであり、const 参照で十分です。コンストラクターを修正することが望ましいですが、それがオプションでない場合は、非 const にキャストします。それには2つのキャストが必要です:

TestGet() : _db(const_cast<Interface_T &>(static_cast<const Interface_T &>(makeMockInterface())))

または単純なテンプレート ヘルパー:

template <typename T>
T &lvalue_cast(const T &v) { return const_cast<T &>(v); }

TestGet() : _db(lvalue_cast(makeMockInterface()))

一時的なものは実際には変更可能であり、セーフガードとして非 const 参照にバインドしないだけなので、両方が明確に定義されています。

于 2012-10-02T09:43:23.983 に答える
0

いくつかの方法があり、いずれもある種の制御の反転を含みます。

私のお気に入りは次のとおりです。

  • インターフェイスへの参照を使用してオブジェクトをコンストラクターに渡します
  • ファクトリ パターンを使用してオブジェクトを作成し、ある種の共有ポインタを返します (再びインターフェイスを使用します)。

このようなもの(基本抽象クラスがあると仮定):

struct Interface
{
  virtual ~Interface(){}
  virtual void foo() = 0;
};
struct Derived : public Interface
{
  void foo(){}
};

struct A
{
  A ( std::shared_ptr< Interface > obj_ ) : obj( obj_ )
  {}

  std::shared_ptr< Interface > obj;
};

//...
A myA( std::shared_ptr< Interface >( new Derived ) );
// ..

上記の例は、コンストラクターに渡す場合です。

于 2012-10-02T10:59:30.257 に答える