通常显式接口由函数的签名式(函数名称、参数类型、返回类型)构成。例如
Widget class:
class Widget{
public:
Widget();
virtual ~Widget();
virtual std::size_t size() const;
virtual void normalize();
void swap( Widget& other );
};
其public接口由一个构造函数、析构函数、函数size、normalize、swap及其参数类型、返回类型、常量性构成。
隐式接口就完全不一样了。它并不基于函数签名式,而是由有效表达式组成。例如下面的模板函数doProcessing:
template<typename T>
void doProcessing( T& w ){
if( w.size() > 10 && w != someNastyWidget )
...
}
T的隐式接口看起来好像有这些约束:
(1)它必须提供一个名为size的成员函数,该函数返回一个整数值。
(2)它必须支持一个operator!=函数,用来比较两个T对象,
但其实这两个约束都不需要满足。T必须支持size函数,但是这个函数也可能从base class继承而得;这个成员函数不一定需要返回一个整数值,甚至不需要返回一个数值类型。它唯一需要做的是返回一个类型为X的对象,该对象加上一个int型后可以调用一个operator>。同样道理,T也不需要支持operator!=,只要存在一个operator!=,它接受一个类型为X的对象和一个类型为Y的对象,T可被转换为X而someNastyWidget可被转换为Y。
总结起来,
对class而言,接口是显式的,以函数签名为中心。多态则是通过virtual函数发生于运行期。
对template参数而言,接口是隐式的,基于有效表达式。多态则是通过template具现化和函数重载解析,发生于编译期。