1。C++ 模板提供了编译期多态的能力,请解释这名话
当我们在面象对向的世界中考虑多态的时候,所考虑的运行时多态,这种能力来自虚函数。基类建立一个接口“合约”,该“合约”由一系统虚函数构成,派生类可以从基类中进行派生,并在不违反合约所蕴涵的语义的前提下重写基类的虚函数 。这样一来,那些期望使用基类对象(通过指针或引用来持用基类对象)来工作的代码使用派生类同样能够运行很好。
不过,运行时时多态有两在主要缺点:首先,这些类型必须位于同一个继承自某个公共基类的类层次结构当中;其次,当虚函数在一个密集的循环当中被调用的时候,你可能会注意到它会带来一些运行时开销,因为通常每次对虚函数的调用都要个额外的间接层虚函数指针,同时,编译器负责根据你的意思将虚函数调用分发到派生类当中对应的函数。
2。下面这个主义是什么?请尽量说全面一些,并务必解释一下为什么这里有两个模板参数而不是一个。
template<class T1,class T2>
void construct(T1*p, const T2&value)
{
new(p)T1(value);
}
construct()函数模板结负责在给定的内存位置构造对象,并同时以某个初始值来初始化它。这里的new 操作符形式称为定位new(placement new),这种形式的new 并不为新对象分配内存,而只不过将新对象放到P所指的内存位置。任何以这种方式new出来的对象都应该通过显式调用其析构函数来销毁,而不是使用delete
那么,为什么construct()具有两个模板参数呢?因为construct()只有一个参数的话,如果要从一个不同类型的对象复制,就得明确地给出参数类型。
例如只有一个参数情况:
template<class T>
void construct(T *p,const T&value)
{
new(p)T(value);
}
//假设p1,p2皆指向未初始化内存
void f(double *p1,Base *p2)
{
Base b;
Derived d;
construct(p1,3.33); //ok
construct(p2,b) ; //ok
construct(p2,3); //错误: T的类型是double 还是 int ?
construct<double>(p2,3); //ok
construct(p2,d) //错误:T1究竟是Base 还是 Derived 呢?
construct<Base>(p2,d); //ok
}