统一初始化语法

C++是个语法特别复杂的语言,在语法分析中时常会出现歧义,例如嵌套模板参数歧义问题:

vector<vector<int>>  vec

在有的编译器上会被解析为vector< vector < int >>vec,也就是把>>当成右移操作符了,不过C++11已经解决这个问题了。咋解决的呢,简单地说,编译器把对>>的分析延迟到语法分析阶段(原来是在词法分析阶段),词法分析器是把”>>”直接当成两个”>”传给了语法分析器,然后在语法分析中如果匹配了template-argument-lis语法,第一个”>”符号会被直接认为是模版结束符,而不是大于,也不是位移符号。

而另一种语法上的歧义是下面这种情况:

class A
{
public:
    A(){};
};
class B
{
public:
    B(const A& t){};
    int getNum(){ return 0; }
};
int _tmain(int argc, _TCHAR* argv[])
{
    B test(A());
    cout << test.getNum();
    return 0;
}

问题出在 B test (A()); 这句话,因为它有两种理解方式:

  • test 是个B类型的对象。 它使用A对象进行初始化。
  • test 是个返回值为B类型对象的函数,它有个类型为A的参数。

我们代码的意图是test是个对象,然而我的VS却把它理解成一个函数,并且告诉我:

error C2228: “.getNum”的左边必须有类/结构/联合

解决的办法就是使用C++11 提供的万能初始化钥匙(统一的初始化语法):

B test{A()};

回过头来看看发生歧义的原因:

  • C/C++中函数声明与定义是可以分开的。函数使用前声明就行。
  • 函数声明可以放在函数中。
  • C++函数声明的时候,形参可以只有类型而没有名称。
  • C++函数声明的参数名在类型后面可以加上(),如void max (int ( ),int ( ))

(完)

posted @ 2015-12-31 16:00  melonstreet  阅读(749)  评论(0编辑  收藏  举报