面向对象的世界总是以显示接口和运行期多态解决问题:【class 支持显示接口和运行期多态】
class Widget {
public:
Widget();
virtual ~Widget();
virtual std::size_t size() const;
virtual void normalize();
void swap(Widget& other);
...
};
void doProcessing(Widget& w)
{
if( w.size() > 10 && w != someNastyWidget ) {
Widget temp(w);
temp.normalize();
temp.swap(w);
}
}
// 由于w的类型被声明为Widget,所以w必须支持Widget的接口
// 由于Widget的某些成员函数是virtual的,所以将在运行期根据w的动态类型决定调用哪个函数
// 即 w对那些函数的调用表现出运行期多态。
如果将上述例子中的 doProcessing 函数转变为函数模板:【template 支持隐式接口和编译期多态,编译期多态实现是依赖 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的任何函数调用,比如 operator > 与 !=,有可能造成template具现化
// 这样的具现行为发生在编译期。
以不同的 template 参数具现化 function templates 会导致调用不同的函数,这便是所谓的编译期多态。
通常显式接口由函数的签名式(函数名称、参数类型、返回类型)构成,隐式接口就不同于此,并不基于函数签名式,而是由有效表达式组成。
template<typename C>
void print2nd(const C& container)
{
if(container.size() >= 2) {
C::const_iterator iter(container.begin());
++iter;
int value = *iter;
std::cout<<value;
}
}
// 这里的iter就是从属名称
// template内出现的名称如果相依于某个template参数,称之为 dependent name(从属名称)
// 如果从属名称在 class 内呈嵌套状,我们称它为嵌套从属名称
// 而这里的value就是local变量,并不依赖于任何template参数,也叫非从属名称
B 是一个模板化基类,D 继承了 B,默认情况下,D 中不能调用 B 的方法,因为 C++ 往往拒绝在 templatized base classes(即 base 类是模板)内寻找继承而来的名称。
template <typename object>
class B:public A<object>
{
public:
void func3()
{
this->func1();//加上this关键字
}
};
template <typename object>
class B:public A<object>
{
using A<object>::func1;
public:
void func3()
{
this->func1();//加上this关键字
}
};
:: 符号明确指出调用的函数位于基类中,但这种方法最差劲,因为如果是调用的虚函数,将会关闭动态绑定行为。template <typename object>
class B:public A<object>
{
public:
void func3()
{
A<object>::func1();
}
};
template<typename T>
class SmartPtr {
public:
template<typename U>
SmartPtr(const SmartPtr<U>& other); // 生成copy构造函数
...
};
// 上述代码是指:对任何类型T和任何类型U,这里可以根据SmartPtr生成一个SmartPtr
// 因为 SmartPtr 有个构造函数接受一个SmartPtr参数。
SmartPtr 创建一个 SmartPtr,却不希望根据一个 SmartPtr 创建一个 SmartPtr,所以就需要对成员 template 产生的函数群进行拣选或筛选:template<typename T>
class SmartPtr {
public:
template<typename U>
SmartPtr(const SmartPtr<U>& other) : heldPtr(other.get()) // 以other的heldPtr
{ ... } // 初始化this的heldPtr
T* get() const { return heldPtr; }
...
private:
T* heldPtr; // 这个SmartPtr持有的内置指针
};
// 使用成员初值列(member initialization list)来初始化
// SmartPtr 之内类型为T* 的成员变量;
// 并以类型为U* 指针(由SmartPtr 持有)作为初值。
)