当涉及到某个界面时,如何从库中扩展类?

时间:2018-01-08 14:07:50

标签: c++ inheritance casting polymorphism

我有一个提供课程Foo的库。我在Foo课程中使用我自己的一些成员函数扩展FooExtended。为了在我的单元测试中使用FooExtended,我必须使它成为可模拟的,因此我创建了一个接口IFoo,这是我在整个代码库中使用的类型。然后我创建了两个接口实现:

  • 班级FooMock - 用于单元测试。

  • 班级FooWrapper - 在实际计划中使用。它主要是FooExtended的包装器,它作为成员存储的实例。

问题:问题在于FooWrapper。我不知道如何利用工厂Lib::create_foo()来创建Foo库,而且还有my_added_function()我在FooExtended中添加的dynamic_cast#include <iostream> #include <memory> #include <cassert> using namespace std; // What's in this namespace is in a 3rd party lib that I cannot change. namespace Lib { class Foo { public: virtual ~Foo() {}; int lib_func() { return 42; } }; // Factory Foo* create_foo() { return new Foo(); } } // namespace Lib /** I want to extend the 3rd party class, and only use this extended class in my project */ class FooExtended : public Lib::Foo { public: float my_added_func() { return 1.0; } }; /** Interface for class Foo, created so that a mock implementation of `FooExtended` can be created for unit tests. */ class IFoo { public: virtual int lib_func() = 0; virtual float my_added_func() = 0; }; /** Mock implemenation of IFoo for unit-tests. */ class FooMock : public IFoo() { // Blah blah } /** Non-mock implementation of IFoo. Just a wrapper for the class with the actual implementation, i.e. FooExtended. */ class FooWrapper : public IFoo { public: int lib_func() override { assert(mFooExt); // This fails because dynamic_cast failed. return mFooExt->lib_func(); }; float my_added_func() override { assert(mFooExt); // This fails because dynamic_cast fails. return mFooExt->my_added_func(); } private: unique_ptr<FooExtended> mFooExt { unique_ptr<FooExtended>( // This dynamic_cast fails. dynamic_cast<FooExtended*>(Lib::create_foo())) }; }; int main() { unique_ptr<IFoo> foo { unique_ptr<IFoo>(new FooWrapper()) }; assert(foo != nullptr); cout << "Starting..."; // Exits the program because of the assert inside. cout << foo->lib_func() << "\n"; cout << foo->my_added_func(); } 失败。

' }{ " : ? > < \ ] [ ' ; / . ,

1 个答案:

答案 0 :(得分:1)

如果您不想为调用虚函数付出代价,可以为Foo创建一个包装器并在程序中使用它:

class IFoo {
  public:
    virtual ~Foo() {};
    virtual int lib_func() = 0;
};

class MyFoo : public IFoo {
  int lib_func() override { _foo.lib_func(); }
private:
  std::unique_ptr<Foo> _foo = create_foo(); // pseudocode
};

现在您可以创建模拟并将其用于IFoo。