- 面向对象编程中的显式接口与运行期多态:
- 显式接口:在面向对象编程中,类的接口是显式的,可在源代码(如类的头文件)中直接看到。例如:
class Widget {
public:
Widget();
virtual ~Widget();
virtual std::size_t size() const;
virtual void normalize();
void swap(Widget& other);
};
Widget
类的显式接口由构造函数、析构函数、size
、normalize
和swap
函数及其参数类型、返回类型和常量性等组成。
- 运行期多态:通过虚拟函数实现。当函数调用涉及虚拟函数时,被调用的特定函数在运行期基于对象的动态类型确定。例如:
void doProcessing(Widget& w) {
if (w.size() > 10 && w!= someNastyWidget) {
Widget temp(w);
temp.normalize();
temp.swap(w);
}
}
在doProcessing
函数中,w
对虚拟函数的调用表现为运行期多态。
- 模板和泛型编程中的隐式接口与编译期多态:
- 隐式接口:模板中参数必须支持的接口是隐式的,由模板中对该参数执行的操作所确定的合法表达式组成。例如:
template<typename T>
void doProcessing(T& w) {
if (w.size() > 10 && w!= someNastyWidget) {
T temp(w);
temp.normalize();
temp.swap(w);
}
}
这里T
(w
的类型)的隐式接口要求T
必须提供size
、normalize
和swap
成员函数,支持拷贝构造函数,以及支持!=
比较操作。但这些要求并不绝对,例如size
函数返回类型不一定是整数,只要能满足后续operator>
的调用即可;!=
操作也不一定要求T
直接支持,只要存在合适的隐式转型能使operator!=
调用合法就行。
- 编译期多态:对包含模板参数的函数调用,如
operator>
和operator!=
,可能会在编译期实例化模板以使调用成功。用不同模板参数实例化函数模板会导致调用不同的函数,这就是编译期多态。例如,当使用不同类型实例化doProcessing
模板时,会根据类型特性生成不同的函数实现。
总之,类和模板都支持接口和多态,但类的接口是显式的,以函数识别特征为中心,多态通过虚拟函数在运行期实现;模板参数的接口是隐式的,基于合法表达式,多态通过模板实例化和函数重载解析在编译期实现。