C++ 当存在';涉及到什么接口?

C++ 当存在';涉及到什么接口?,c++,inheritance,casting,polymorphism,C++,Inheritance,Casting,Polymorphism,我有一个提供classFoo的库。我在类FooExtended中使用自己的一些成员函数扩展Foo。为了在我的单元测试中使用FooExtended,我必须使其可模拟,因此我创建了一个接口IFoo,这就是我在整个代码库中使用的类型。然后,我创建了两个接口实现: 类FooMock-用于单元测试 类FooWrapper-在实际程序中使用。它主要是FooExtended的包装器,它作为成员存储一个实例 问题:问题在于FooWrapper。我不知道如何使用工厂Lib::create_foo()来创建库所

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

  • FooMock
    -用于单元测试

  • FooWrapper
    -在实际程序中使用。它主要是
    FooExtended
    的包装器,它作为成员存储一个实例

问题:问题在于
FooWrapper
。我不知道如何使用工厂
Lib::create_foo()
来创建库所需的
foo
,但也有我在
FooExtended
中添加的
my_added_函数()。
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();
}
#包括
#包括
#包括
使用名称空间std;
//这个名称空间中的内容位于我无法更改的第三方库中。
名称空间库{
福班{
公众:
虚拟~Foo(){};
int lib_func(){
返回42;
}
};
//工厂
Foo*创建_Foo(){
返回新的Foo();
}
}//名称空间库
/**我想扩展第三方类,并且只使用
这是我项目中的扩展类*/
类FooExtended:public Lib::Foo{
公众:
float my_added_func(){
返回1.0;
}
};
/**类Foo的接口,创建该接口是为了
可以为单元测试创建“FooExtended”的实现*/
类IFoo{
公众:
虚int lib_func()=0;
虚拟浮点my_added_func()=0;
};
/**单元测试IFoo的模拟实现*/
类FooMock:public IFoo(){
//废话
}
/**IFoo的非模拟实现。只是一个类的包装器
实际实施,即扩展。*/
类FooWrapper:public IFoo{
公众:
int lib_func()重写{
assert(mFooExt);//此操作失败,因为动态强制转换失败。
返回mFooExt->lib_func();
};
float my_添加了_func()覆盖{
assert(mFooExt);//由于动态强制转换失败,因此此操作失败。
返回mFooExt->my_added_func();
}
私人:
唯一的\u ptr mFooExt{
独特的(
//此动态_cast失败。
动态_cast(Lib::create_foo()))
};
};
int main(){
unique_ptr foo{unique_ptr(new FooWrapper())};
断言(foo!=nullptr);

cout如果您不怕为调用虚拟函数付出代价,您可以为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{
公众:
虚拟~Foo(){};
虚int lib_func()=0;
};
类MyFoo:公共IFoo{
int lib_func()重写{{u foo.lib_func();}
私人:
std::unique_ptr_foo=create_foo();//伪代码
};

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

如果必须通过
Foo*create\u Foo()
创建
Foo的实例,那么您就不能从
Foo
派生。
FooExtended
的基类子对象显然不是也不能是由
create\u Foo
创建的。最好的方法是创建一个包含(可能是智能的)指向
Foo
作为成员的指针。虚拟函数成本?您有度量,在真实代码中?您知道比查表更好的解决方案?谢谢您的回答。您是对的:在这种情况下,我的扩展函数应该添加到包装器中,而不是添加到派生类
footextended