如果你不清楚常数映射为型别的话,你可以看我的另外一篇博客,,这里有有简短的介绍.C++ 常数映射为型别.
运行时分发.
相信编写过程序的人都知道,if,else语句或者是其他的判断语句都有分发跳转的功能,根据不同的运行时参数决定程序的执行走向。
编译期分发
编译期就已经决定了调用哪一个函数,说到这里,可能还是云里雾里,没关系,下面继续看.
这里我们假设,现在有一个类NitifyContainer(这个例子来源于书籍《C++设计新思维泛型编程与设计模式之应用》),为了复制NitifyContainer中的某一个类型为T的对象,你想调用它的copy构造函数(针对非多态型别),针对多态型别的话,调用虚函数clone,提供bool模板参数,提供调用者的信息(是否是多态),代码如下:
template<class T, bool isPolymorphic>
class NitifyContainer {
public:
void doSomething() {
T *tt = new T();
if (isPolymorphic) {
T *ts = tt->clone();
ts->handle();
} else {
T *nt = new T(*tt);
nt->handle();
}
}
};
下面运行这段代码:
NitifyContainer<Person, false> container;
container.doSomething();
如果你现在编译这个代码的话,那么恭喜你,无法通过编译
你可能会想,我的程序都不会进入到这里,编译它干啥??我也这样想,但是编译器不这么想啊
嗯,看来这种静态分发的方法是不行的,下面我们继续来看。
更改后的代码如下所示,非常有意思
template<int a>
struct IntType {
int b = a;
};
template<class T, bool isPolymorphic>
class NitifyContainer {
private:
void doSomething(T *obj, IntType<true>) {
cout << "clone called" << endl;
T *copyObj = obj->clone();
}
void doSomething(T *obj, IntType<false>) {
cout << "copy constructor called" << endl;
T *copyObj = new T(*obj);
}
public:
void doSomething(T *obj) {
doSomething(obj, IntType<isPolymorphic>());
}
};
int main() {
NitifyContainer<Person, false> container;
container.doSomething(new Person("obama"));
}
再一次编译运行,完美运行
《C++设计新思维泛型编程与设计模式之应用》中的一句话,清楚了描述了这种技巧之所以能够使用的原因
所以这样一来,就算你没有定义某一些函数,编译也不会抛出异常。