难度:
文前提醒:看这篇文章时须家长陪同并引导,以免走火入魔
先看看下面的代码?
struct A
{
A(){}
};
template<typename T>
void func(T() )
{}
int main()
{
A a( A() ); //(1), OK
func( A() ); //(2), Wrong
a = 5; //(3), Wrong
}
(1)、 A a( A() ); 是什么意思?
在这里是用A()创建一个对象,然后初始化对象a吗?这里真正的语义是a是一个参数为返回A对象的无参函数指针的函数,所以它的真面目应该是A a( A (*)() ),其中的A()是个函数类型,在实际作参数时会退化为一个A(*)()指针 。而这句仅仅起到声明函数的作用。重点就在于A()并不是创建对象,而是一个无参的、返回为A的函数类型
(2)、 func( A() ); 为什么会出错呢?
这里虽然函数模板func的参数同样也是一个函数类型,那为什么会出错呢? 其实在这里A()就不是一个函数类型了,而是创建一个匿名对象。那么这个函数即成了 void func( A ),而原本的函数模板func 类型是void ( T (*)() ),很明显参数类型不匹配。
(3)、 a = 5; 现在应该没有任何疑问了
把int 传递给 A ()( A (*)() ),地球人都知道是错的。
千万别走火入魔!
是什么导致了(1)和(2)中的A()表现出不同的语义呢?
答:在这里的 A() 就具有二义性:它即可以解释为新创建的类 A 的一个临时对象(在此过程中要调用 A 的构造函数),也可以解释为一种函数类型声明:其返回值为A类型的对象,函数参数为空。如果是前种解释,则 a 为类 A 的一个对象;如果是后一种,则整句就是一个函数声明:声明了一个函数 a,其返回值类型为 A,函数参数(省略了参数名。对于函数声明这样做是可以的)是上述的一个函数类型。到底是前一种还是后一种解释取决于它所在的语义环境。
更多
struct A
{
A(int ){}
};
A a(A(1)); 在这里A(1) 就不可能是“类型”了,因为其中有个1,而A(1)就成了一个转换函数调用形式,所以A(1)这里是调用的A(int)。
非常感谢whyglinux,为本文指出错误并作出修改。
//The End