【发布时间】:2011-12-16 23:07:39
【问题描述】:
在类层次结构的设计中,我使用了一个抽象基类,它声明了派生类将实现的各种方法。从某种意义上说,基类与 C++ 中的接口一样接近。但是,有一个具体问题。考虑下面声明我们的接口类的代码:
class Interface {
public:
virtual Interface method() = 0;
};
class Implementation : public Interface {
public:
virtual Implementation method() { /* ... */ }
};
当然,这不会编译,因为您不能在 C++ 中返回抽象类。为了解决这个问题,我使用了以下解决方案:
template <class T>
class Interface {
public:
virtual T method() = 0;
};
class Implementation : public Interface<Implementation> {
public:
virtual Implementation method() { /* ... */ }
};
这个解决方案很有效,而且一切都很好,但对我来说,它看起来不是很优雅,因为多余的文本位将成为接口的参数。如果你们能指出我们与此设计有关的任何其他技术问题,我会很高兴,但这是我目前唯一关心的问题。
有什么办法可以去掉那个多余的模板参数?可能使用宏?
注意:有问题的方法必须返回一个实例。我知道如果method() 返回一个指针或引用,就没有问题。
【问题讨论】:
-
您使用的成语称为Curiously Recurring Template Pattern。我想你可以用
#define DERIVE_TEMPLATE_BASE(Derived, Base) class Derived : public Base<Derived>之类的宏替换类声明,但它看起来非常难看,可能会让你的编辑器感到困惑。底线 - 是的,有一个冗余,但它是公认的和可识别的成语。 -
@gwiazdorrr:看起来还不错。如果这是一个公认的习语,那么我可以假设它对“界面”的用户来说不会太陌生,对吗?
-
另外请注意,(至少在本例中),将调用设为虚拟是没有意义的,因为 CRTP 需要已知的大多数派生类型才能使用基本类型。
-
@MooingDuck:这是一个有趣的效果。析构函数呢?
-
只要你不调用
Interface<Implementation>的析构函数就没有关系。你不会,因为没有理由用std::vector<Interface<Implementation>>代替std::vector<Implementation>。
标签: c++ oop inheritance abstract-class