c++中比较容易有歧义的语法
2017-10-22 12:20
225 查看
无法确定是调用类构造函数还是一个函数指针指向类的类型
代码如下:
这样的话testIfMethodOrConstructor函数可理解为声明一个无且返回值为Monkey的函数指针,也可理解为声明一个Moneky类型的对象,使用类的无参构造函数对其进行初始化。
这里编译器的实际情况是默认为了指针,所以可能与我们想要的结果不太一样,于是当test函数被调用的时候不会打印出语句。
修改方法可以为
- 去掉m1后面的括号,这样就不会认为是函数的可能,只能是一个类变量的声明
- 亦或者是调用initializer_list初始化,消除歧义
这里的initializer_list初始化,在实际中就是{}进行赋值初始化,这种用法在string中也有string s={‘a’,’b’};string实际是char数组组成的。
所以修改后的上面test函数被调用后会输出两条打印语句
在上面基础上更一步,上面的test函数两种改进后的做法是显示的调用了Monkey的无参构造函数,这里我们将Monkey的构造函数修改如下:
将其变为带参数的explicit函数,类中没有无参构造函数,所以testIfMethodOrConstructor中的情况为
explicit的区别于此,言归正传,这里在Monkey修改后的情况下,增加一个Tiger类,如下:
testTiger()函数被调用后无法输出Tiger的显示构造函数,说明这里的调用有歧义。这里之所以有歧义的地方在Tiger tt(Monkey(i))不会被理解为一个带初始参数的Tiger对象,而被曲解为函数声明Tiger tt(Monkey i),一个Monkey参数的返回值为Tiger的函数,i包围的括号变成了冗余。这与上面的歧义相似,因此不会有任何构造函数语句输出。
修改方法,
Tiger构造函数外面再加一层括号()
Tiger构造函数的括号()改为中括号,也就是initializer_list初始化的形式
输出语句为
总结:之所以造成歧义,个人发现最大的原因在于小括号()造成的函数声明与类的默认构造函数的不明确,感觉最好用的做法就是初始化用{},当然这得c++11的支持特性
代码如下:
class Monkey{ public: Monkey(){ std::cout<<"Monkey constructor has been used"<<std::endl; } }; void testIfMethodOrConstructor(){ Monkey m1();//有歧义 }
这样的话testIfMethodOrConstructor函数可理解为声明一个无且返回值为Monkey的函数指针,也可理解为声明一个Moneky类型的对象,使用类的无参构造函数对其进行初始化。
这里编译器的实际情况是默认为了指针,所以可能与我们想要的结果不太一样,于是当test函数被调用的时候不会打印出语句。
修改方法可以为
- 去掉m1后面的括号,这样就不会认为是函数的可能,只能是一个类变量的声明
- 亦或者是调用initializer_list初始化,消除歧义
#include <initializer_list> ... void testIfMethodOrConstructor(){ // Monkey m1(); Monkey m2; Monkey m3{};//注意这里是中括号 }
这里的initializer_list初始化,在实际中就是{}进行赋值初始化,这种用法在string中也有string s={‘a’,’b’};string实际是char数组组成的。
所以修改后的上面test函数被调用后会输出两条打印语句
在上面基础上更一步,上面的test函数两种改进后的做法是显示的调用了Monkey的无参构造函数,这里我们将Monkey的构造函数修改如下:
explicit Monkey(int i){ std::cout<<"Monkey constructor has been explicit used"<<std::endl; }
将其变为带参数的explicit函数,类中没有无参构造函数,所以testIfMethodOrConstructor中的情况为
void testIfMethodOrConstructor(){ // Monkey m1(); Monkey m2; //错误,没有无参构造函数 Monkey m3{}; //错误,没有无参构造函数 Monkey m4=1;//注意,无法隐式转换 Monkey m5{1};//正确 Monkey m6(1);//正确 }
explicit的区别于此,言归正传,这里在Monkey修改后的情况下,增加一个Tiger类,如下:
class Tiger{ public: explicit Tiger(Monkey m){ cout<<"Tiger constructor has been explicit used"<<endl; } }; void testTiger(){ int i=3; Tiger tt(Monkey(i)); //调用有歧义 cout<<"end of testTiger"<<endl; }
testTiger()函数被调用后无法输出Tiger的显示构造函数,说明这里的调用有歧义。这里之所以有歧义的地方在Tiger tt(Monkey(i))不会被理解为一个带初始参数的Tiger对象,而被曲解为函数声明Tiger tt(Monkey i),一个Monkey参数的返回值为Tiger的函数,i包围的括号变成了冗余。这与上面的歧义相似,因此不会有任何构造函数语句输出。
修改方法,
Tiger构造函数外面再加一层括号()
Tiger构造函数的括号()改为中括号,也就是initializer_list初始化的形式
void testTiger(){ int i=3; Tiger tt(Monkey(i)); //函数声明 Tiger tt1((Monkey(i))); //修改方法一 Tiger tt2{(Monkey(i))}; //修改方法二 cout<<"end of testTiger"<<endl; }
输出语句为
Monkey constructor has been explicit used Tiger constructor has been explicit used Monkey constructor has been explicit used Tiger constructor has been explicit used end of testTiger
总结:之所以造成歧义,个人发现最大的原因在于小括号()造成的函数声明与类的默认构造函数的不明确,感觉最好用的做法就是初始化用{},当然这得c++11的支持特性
相关文章推荐
- 列出比较容易忘记的 C++(C)语言语法及标准库
- C++ 11中几个我比较喜欢的语法(二)
- QTreeWidget的一个例子,C++语法和item迭代循环都比较巧妙
- OpenCV程序加速及C++中一些编程语法速度比较
- 一些背我遗忘又比较有用的C++语法知识
- 比较java和C++的面向对象语法
- C++ 11中几个我比较喜欢的语法
- 在C/C++开发中容易被忽略却比较有用的两个函数
- C++ 11:比较诡异的一些语法
- BV、VFP、C++、Access、Photoshop 以下这些计算机二级考试内容中 那种是比较容易考的呢
- C++.NET与C#的编码区别 ,vb.net与c#的语法比较
- [语法比较][指针/引用]Lava和C/C++语法比较
- 比较Java和C++的访问控制语法
- JAVA基础篇一(Java,C++基础语法的比较)
- C++比较特殊的构造函数和初始化语法
- C++与Java语法比较
- C++ 容易忘的基本语法和特性
- LUA与C++的语法比较
- C++ 11中几个我比较喜欢的语法(三)
- C++中的模板比较容易混淆的几个概念:类模板和类成员模板以及函数模板