如何隐藏模板基类的参数类型

时间:2018-07-15 15:03:25

标签: c++ design-patterns object-slicing

不确定这是否可能,但是可以解决...

我正在尝试通过执行以下操作来隐藏模板基类的参数:

  • 公开一个通用界面
  • 实现通用接口的实现模板基类
  • 实现几个具体的派生类
  • 使用工厂类实例化具体的派生类

到目前为止,还不错,但是问题是我的工厂类的返回类型是IBase,因此调用了foo的默认实现,而不是DerivedA或DerivedB:(

对这种方法有用吗?还是回到绘图板?

// Common interface
class IBase {
public:
  virtual std::string foo() { return "IBase"; };
}

// Template base class
template <typename T>
class Base : public IBase {
public:
  Base(T value) : m_precious(value) {}
  virtual ~Base() {}
protected:
  T m_precious;
}

// Concrete derived classes
class DerivedA : public Base<int> {
public:
  DerivedA(int value) : Base<int>(value) {}

  virtual std::string foo() override {
   return "DerivedA";
  };
}

class DerivedB : public Base<float> {
public:
  DerivedB(float value) : Base<float>(value) {}

  virtual std::string foo() override {
   return "DerivedB";
  };
}

// Factory interface
class Factory {
public:
  template<typename T>
  static IBase create(T value);
};

template<>
IBase Factory::create<int>(int value) {
  return DerivedA(value);
}

template<>
IBase Factory::create<float>(float value) {
  return DerivedB(value);
}

// Caller
int main() {
  int   valueA = 3;
  float valueB = 3.14;

  // This is how I want to use the API
  IBase A = Factory::create(valueA);
  IBase B = Factory::create(valueB);

  std::cout << A.foo() << std::endl;
  std::cout << B.foo() << std::endl;
}

上面的代码打印:

IBase
IBase

但是我想要这个:

DerivedA
DerivedB

1 个答案:

答案 0 :(得分:1)

您当前有对象切片,您的代码应类似于:

// Factory interface
class Factory {
public:
  template<typename T>
  static std::unique_ptr<IBase> create(T value);
};

template<>
std::unique_ptr<IBase> Factory::create<int>(int value) {
  return std::make_unique<DerivedA>(value);
}

template<>
std::unique_ptr<IBase> Factory::create<float>(float value) {
  return std::make_unique<DerivedB>(value);
}

使用方式:

auto A = Factory::create(valueA);
auto B = Factory::create(valueB);

std::cout << A->foo() << std::endl;
std::cout << B->foo() << std::endl;