使用模板(而不是继承)指定类中的类型

Specification for the type in a class using templates (instead of inheritance)

本文关键字:类型 继承      更新时间:2023-10-16

当从一个类继承时,您只需通过查找层次结构就知道强加给您的需求和限制。例如,您可以通过查看父类来确定需要定义哪些方法(纯虚方法)。如果选择使用模板(如果它符合要求),那么事情就不那么清楚了。模板类的方法可能期望type有几个方法存在。

我遇到了一个必须使用的复杂类。我不知道我的type(类/对象)应该有什么方法。我能找到的唯一方法是编译,编译器会让我知道哪些方法是预期的。这就像从抽象类继承而不访问头文件一样。这有点麻烦,因为找出方法规范(签名)很耗时。

现在,类的原始设计者可能已经放了一些文档,关于哪些方法预计会出现和他们的签名,但我不禁想知道是否有一种方法可以自我记录代码(或者已经是,我不知道如何查看它?)。编译和查看错误不可能是唯一的方法,不是吗?

你本质上是在描述c++ 0x概念要通过向程序员提供一种在编译时对type强制要求的方法来解决的那种问题。然而,由于时间限制,它于2009年7月被删除。

在Boost中有一个仅库的解决方案,称为概念检查库(BCCL)。然而,BCCL和c++ 0x概念之间存在差异。这是我们现有的语言中最接近概念的东西。

如果您不想使用BCCL,那么文档是下一个最好的选择。

在c++ 11中有一个关于概念的提案可以解决这个问题:概念本质上是对模板参数必须满足的接口的描述。如果您现在需要的话,可以从Boost概念检查库中获得类似的功能,但是必须从一开始就设计一个类来使用概念断言,因此如果您有一个现有的库,那么您就不走运了。

c++ 11增加了static_assert(可以在c++ 03中通过BOOstrongTATIC_ASSERT进行模拟)。现在,您可以编写许多将在编译时触发的断言,并在其中添加可读的文档,说明为什么会触发该断言。根据你要测试的工具(即c++ 11的type_traits或仅boost.type_traits),你可以或多或少地使用它(也考虑使用decltype来检查做某些事情的可能性,可能结合sizeof技巧,在泛型中很难分辨)

使用组合和纯虚拟类避免了这个问题。使用和理解接口更容易。更容易理解实现如何实现接口。单元测试更容易。

struct B {
  virtual ~B() {}
  virtual void foo() const = 0;
  virtual void bar() const = 0;
};
struct D : public B {
  virtual ~D() {}
  virtual void foo() const {foo_thing.call();}
  virtual void bar() const {bar_thing.call();}
private:
  some_foo_like_thing foo_thing;
  some_bar_like_thing bar_thing;
};

我希望讨论纯虚拟接口中应该和不应该做什么应该更容易,尽管实际情况可能会有所不同。;)

欣赏一件事物所需要的信息越多,就越难对它进行推理。如果你的类依赖于它的父类的实现,那么你就必须理解它和它的每一个前身。不仅是接口,还有实现。

如果我要设计一种语言,实现继承甚至不会是一个选项。