一、c++允许定义指向类成员的指针,包括类函数成员指针和类数据成员指针
格式如下:
class A
{
public:
void func(){printf("This is a function!\n");}
int data;
};
void (A::*p)()=&A::func;//带有取址符号,普通函数指针不带该符号,可能防止编译歧义,和traits机制中typename作用类似
int A::*q=&A::data;
p();//error:非静态成员函数的使用必须依附于对象
A a;
a.data=1;
(a.*p)();//output:This a function!
cout<<a.*q<<endl//output:1
二、非类型类模板参数:
template <class T,int inst>
struct B
{
T t;
int fun(){cout<<inst<<endl;}
}
B<int,10> b;
b.fun();//output:10
三、函数指针返回值:
void (*fun(void(*f)()))(){}
黑色部分形成了一个函数指针的形式,红色部分函数名,绿色部分是与之对应的参数列表,函数指针类型与函数结合形成了一个函数定义的形式,当然也可用typedef简化形式
四、内嵌型别示例:
template <class T,int inst>
struct C
{
T t;
template <class U>
void fun(){cout<<"a nested class"<<endl;};
void fun(){cout<<inst<<endl;}
class M;
};
template <class T,int inst>
class C<T,inst>::M
{
int a;
};
main:
C<int,10> c;
c.fun<int>();//output:a nested class
五、模板参数推导机制和内嵌型别的作用:
template <class T>
void fun(T a){cout<<a<<endl;}
fun(10);//自动设T为int类型
下面一种情况,推导机制无法满足需要
template <class T,class U>
U fun(T a){cout<<a<<endl;return (U)a;}
为了泛化算法,c++引入了迭代器(或者叫做智能指针),算法以迭代器做参数的时候可能会用到迭代器所指向的实际类型,这就需要迭代器携带有他所指向的类型的信息),这就实现了类型信息的传递。
实际上参数推导机制和关联型别都是编译时期的策略,都是为了得出算法中用到的型别,为了配合编译器的工作所增加的语言特性
对于泛化算法而言,通常在实例化的时候并不指定模板参数,这时就要用到参数推导了,但是迭代器作为算法的参数时,如果要用到迭代器的关联型别,这时参数推导并不能得出该关联型别,所以迭代器必须自己携带相关联型别(类自身通过typedef T value_type这样一句来使自己携带自身的类型),否则算法不能进行型别相关的动作。
实际上,stl中只要不指定模板参数,基本上都会先进行参数推导,得到迭代器的型别,再通过traits机制获取迭代器相关型别
这里还要说一下类模板的偏特化,当然是对同一个类来说的,比如对一个类 class C 它的偏特化版本需要对模板参数进行限定(加上一层条件)比如class C<T*>模板参数需要是T*类型才可以通过这个偏特化模板进行实例化。
综上,当人们想要实现自己的某一理念的时候,往往会伴随着开辟新的语法特性来满足这种需求。
references:
http://msdn.microsoft.com/zh-cn/library/windowsphone/develop/k8336763(v=vs.71).aspx