Skip to content

Latest commit

 

History

History
43 lines (34 loc) · 2.13 KB

File metadata and controls

43 lines (34 loc) · 2.13 KB

条款41:了解隐式接口和编译期多态

Template与泛型的世界,与面向对象有根本上的不同。在此世界中显式接口和运行期多态仍然存在,但重要性降低。反倒是隐式接口和编译期多态变得重要。看看下面的函数模板:

template <typename T> 
void doProcessing(T& w) {
  if (w.size() > 10 && w != someNastyWidget) {
    T temp(w);
    temp.normalize();
    temp.swap(w);
  }
}
  • w必须支持一种接口,由template中执行于w身上的操作来决定。本例看来w的类型T必须支持size, normalize和swap成员函数,copy构造函数,比较运算符。这一组表达式便是T必须支持的一组隐式接口。
  • 凡涉及w的任何函数调用,有可能造成template的实例化,使这些调用得以成功。这样的实例化行为发生在编译期。以不同的template参数实例化函数模板会导致调用不同的函数,这就是所谓编译期多态。

通常显式接口由函数的签名构成,例如Widget class:

class Widget {
public:
  Widget();
  virtual ~Widget();
  virtual std::size_t size() const;
  virtual void normalize();
  void swap(Widget& other);
};

隐式接口就完全不同了,它并不基于函数签名,而是由有效表达式组成。上述函数模板中,T的隐式接口好像有这些约束:

  • 它必须提供一个名为size的成员函数,该函数返回一个整数。
  • 它必须支持 operator!=,用来比较两个T对象。这里我们假设someNastyWidget的类型为T。

但是由于运算符重载带来的可能性,这两个约束都不需要满足。T必须支持size成员函数,但是这个函数不需要返回一个整数值,只需要返回一个类型为X的对象,这个对象必须和10支持 operator>。其他运算符重载同理。

请记住

  • class和template都支持接口和多态。
  • 对class而言接口都是显式的,基于函数签名。多态则是通过virtual函数发生于运行期。
  • 对template参数而言,接口是隐式的,基于有效表达式。多态则是通过template实例化和函数重载决议发生发于编译期。