87型雨水斗和65雨水斗:[c primer plus]c 函数模版,类模版,实例化,具体化,模版作参数,模...

来源:百度文库 编辑:偶看新闻 时间:2024/03/29 16:13:44
  [c++ primer plus]c++ 函数模版,类模版,实例化,具体化,模版作参数,模版的友元2009年11月26日 星期四 19:00

[c++ primer plus]c++ 函数模版,类模版,实例化,具体化,模版作参数,模版的友元 收藏
模版不是类或函数,它们是c++编译器指令,它只是一个用于生成类或函数的方案,说明如何生成类或函数。 具体生成时,称为实例化(instantiation)或具体化(specialization)。因此,模版不能单独编译,必须与特定的实例化请求一起使用。最简单的办法就是将所有模版信息放入一个头文件里,使用时include这个头文件。如果编译器支持export关键词,则可以将“类模版”的声明与定义分开存放在.h和.cpp中。

1. 函数模版的重载(利用可以重载的特征标)

template
void Swap(Any& a, Any& b);

//override
template
void Swap(Any* a, Any* b, int n);

template
void Swap(Any& a, Any& b)
...{
    Any temp; temp = a; a = b; b = temp;
}

template
void Swap(Any* a, Any* b, int n)
...{
    Any temp;
    for (int i = 0; i < n; i++)
    ...{ temp = a[i]; a[i] = b[i]; b[i] = temp; }
}
main( )
{
    int i, j;
    double k[10], m[10];
    Swap(i, j);         //显示实例化为Swap(int&, int&);
    Swap(k, m, 10);    //显示实例化为Swap(double*, double*, int);
}
2. 函数模版的显式实例化,即可以命令编译器直接创建 template 的实例,把 class Any 实例化。

//explicit instantiation
template void Swap(int&, int&);
template void Swap(Cjob&, Cjob&);
3. 函数模版的显式具体化,它不使用模版来生成函数定义,而应使用独立的、专门的函数定义。显式具体化要有自己的函数定义,而显式实例化则不需要,这是两者本质的区别。两者的相同之处是:都生成了一个具体的函数,而不再是模板。

// explicit specialization,这两种格式显式实例化的格式等价,只需要一种就可以。
template <> void Swap(Cjob& a, Cjob& b);
template <> void Swap(Cjob&a, Cjob& b);

template <> void Swap(Cjob& a, Cjob& b)
...{
    string tStr;
    tStr   = a.name;
    a.name = b.name;
    b.name = tStr;
}

template <> void Swap(Cjob& a, Cjob& b)
...{
    string tStr;
    tStr   = a.name;
    a.name = b.name;
    b.name = tStr;
}

4. 函数模版的部分具体化,部分具体化与显式具体化的区别在于:前者还是一个函数模板,而后者则已经是一个函数。前者的函数定义中,必然还有typename类型待定,这个类型将在函数模板被调用的时候得到“隐式”的具体化。

template
void Swap(T1& a, T2& b, T3& c);

//explicit specialization
template void Swap(T1& a, T2& b, int& c);

//部分具体化,可以引入各种限制
template void Swap(T1& a, T2& b, T2& c);
tempate void Swap(T1& a, T1* &b, T1* &c);

template
void Swap(T1& a, T2& b, T3& c)
...{
..............
}

template void Swap(T1& a, T2&b, int& c)
...{
..............
}

template void Swap(T1& a, T2& b, T2& c);
...{
.............
}

template void Swap(T1 &a, T1* &b, T1* &c)
...{
..............
}
5. 类模版之内与之外:在之内声明时可以忽略类型,之外必须Stack带上类型。

template
class Stack
...{
public:
    Stack& operator= (const Stack& st);
}

template
Stack & Stack :: operator=(const Stack& st)
...{
}
main ( )
{
    Stack st;    //隐式的实例化
}
6. 类模版的默认类型参数,不能为函数模版提供默认的类型参数。

template
class Topo
...{
........
};
Topo m1;
Topo m2;    //使用默认类型
7a. 类模板的显式实例化

template
class SortedArray
...{
public:
    T val
};

template class SortedArray;

main ( )
...{
    SortedArray sa; //模板类与模板函数的区别在于:前者被调用时,总是要带有,而后者则不带。因为后者可以从形式参数来实例化或具体化模板;而前者则只能靠这个后缀,由编译器决定生成哪种类型。(即使已经显式实例化了,也要带上后缀。)
}
7b. 类模板的显式具体化

template
class SortedArray
...{
........
};

//显式具体化,定义新的类功能。
template <> class SortedArray
...{
........
};
main ( )
{
    SortedArray sa;
}
7c. 类模版的部分具体化

template
class SortedArray
...{
public:
    SortedArray()
    ...{
        printf("1 ");
    }

    T1 val1;
    T2 val2;
    T3 val3;
};

template
class SortedArray
...{
public:
    SortedArray()
    ...{
        printf("2 ");
    }

    T1 val1;
    T2 val2;
};

template
class SortedArray
...{
public:
    SortedArray()
    ...{
        printf("3 ");
    }

    T1 val;
};

template <>
class SortedArray
...{
public:
    SortedArray()
    ...{
        printf("4 ");
    }
};

int main(int argc, char* argv[])
...{
    SortedArray sa1;
    SortedArray sa2;
    SortedArray sa3;
    //SortedArray sa4;

    printf("Hello World! ");
    return 0;
}
8. 模版作为模版类的成员

template
class beta
...{
private:
    template
    class hold;
    hold q;
    hold n;
public:
    template
    U blab(U u, T t);
};

//member define
template
template
class beta::hold
...{
private:
    V val;
public:
    V Value() const ...{return val;}
};

template
template
U beta::blab(U u, T t)
...{
    ........
};
9. 模版作为模版的参数,vc++不支持这种使用,g++支持。

template
class Stack
...{
....
};

template