模板实例化的抽象基类的子类的构造函数-需要替代设计模式

Constructor of a subclass of a template-instantiated abstract base class - alternative design patterns required

本文关键字:设计模式 子类 实例化 抽象 基类 构造函数      更新时间:2023-10-16
我有一个这样的模板:
template<typename T>
struct foo {
  foo(T t) {
    //code
  }
  virtual double computation() = 0;
  //other members
};

我希望用户提供自己的子类与自定义的Tcomputation()像这样:

struct my_foo : public foo<std::string> {
  double computation() override { return 9.99; }
};

问题是这不起作用:

my_foo("hello");

我必须要求用户为每个子类创建一个新的构造函数,即使它所做的只是调用超类构造函数。这看起来很傻。

你能建议一些可能更适合我的"设计模式"吗?

我相信这和模板没有直接关系。

这仅仅是因为:在c++中,构造函数是不可继承的。

试试这个例子,你会发现它不起作用:

class Parent {
public:
    Parent(int i) {
        cout << "i " << i << endl;
    };
};
class Child : public Parent {
};
int main(int argc, char** args) {
    Child child(1);
    return 0;
}

因为默认情况下,Child的构造函数将调用Parent的无参数函数。

更改Child以提供适当的actor将解决问题:

class Child : public Parent {
public:
    Child(int i):Parent(i) {
    }
};

在这个例子中,我为Child创建了一个带有1个参数的actor。这个子节点将调用父节点的Parent(int)节点。

在您的问题中,您说要求子类创建actor是愚蠢的:这一点也不愚蠢!您永远不会知道子类希望如何实例化它的类。基于语义,某些子类可能只适合用两个参数来构造。

如果你真的想神奇地完成它,一个最简单的方法就是创建宏来"生成"子类的类声明和相应的变量。然而,这样做很少有意义。

从您的示例中我可以看到,您希望用户指定类型和计算函数。由于您没有提供虚拟析构函数,我假设您不想要多态地使用结果模板实例化,例如,您不想在同一位置存储/交换不同的foo<string>实现。换句话说,纯虚函数的唯一目的似乎是强制客户端实现computation()

您还希望模板的构造函数可以使用,而不需要客户端重新实现或显式地将其导入到自己的类中。只有当my_foofoo的实例而不是派生类时才能实现。

在这种情况下,您可以使用基于策略的设计:
template<typename T, typename ComputationPolicy>
struct foo : ComputationPolicy {
  foo(T t) {
    //code
  }
  void bar() {
    double d = ComputationPolicy::computation(); //just use it!
  }
  //...
};

模板的用户现在必须定义具有函数computation()的类型,返回可转换为double的值,否则模板无法实例化:

struct myComp  {
  double computation() { return 9.99; }
};
typedef foo<std::string, myComp> my_foo;
my_foo("hello");