记录一下排坑过程(C++报错 reference to ‘count’ is ambiguous);
涉及到#命名空间的知识点,以及一些C++11新标准(auto
)的记录,只想解决同类问题的小伙伴可以直接跳转问题解决或者一图解决问题;
C++全局(文件)变量
代码重现(简化)
#include<bits/stdc++.h>using namespace std;int count=0;void fun(){printf("%d",++count);}int main(){fun();}
问题分析
代码看上去再正常不过了,甚至对这其中的概念不清楚可能就完全不知道哪里错了;这里先卖个关子,来看报错信息,养成良好的解决问题的习惯是关键;
[Error] reference to 'count' is ambiguous
实际问题中可能报错信息有连锁反应是一长串,这个报错其实也是,我们要学会从报错信息中提取关键信息来解决问题,上面是我提取之后的结果,原报错信息是这样的:
count
定义是模糊的,std::count
,注意,错误点(百度翻译的候选人我觉得不太恰当)是int count
;报错信息解析后基本上已经明了了,是命名空间std中已经有了count这个变量名,而刚开始学C++的时候就经典的写题模板是:
#include<iostream>using namespace std;int main(){return 0;}
可能许多同学到现在还都不明白use namespace std
这句话的意思,这里涉及到了#命名空间;
但是笔者有幸参加了acm比赛(啥也不会);侥幸得知了
#include<bits/stdc++.h>/*注意Visual Studio不包含该头文件,需要读者自行下载配置*/
这个头文件,基本上顺手就写上了,里面封装了基本上常用的库函数之类的,能节省时间吧~
但是恰恰就是这个行为习惯导致了这个错误,众所周知打ACM少不了使用STL
,而STL
内已经占用了count这个变量,之后我们定义的count变量就引起了变量冲突,这点笔者在看刘汝佳老师的紫书``STL`部分时确实提到过尽量不要使用count这个变量因为已经定义过了;
解决问题
笔者遇到问题第一时间也是没有想到太多,由于全局变量count仅仅在fun()函数内使用过(实际上机时也是),故此将变量定义在fun函数内部,以static关键词修饰;
#include<bits/stdc++.h>using namespace std;//int count=0;void fun(){static int count=0;printf("%d",++count);}int main(){fun();}
问题完美解决,但是知其然要知其所以然,故此才找到了上述的错误,有时候解决问题并不是一气呵成的;
这个解决办法确实不错,那么还有其他的方法吗?这个方法明显有种太怂了的感觉,遇到问题就逃避(手动滑稽)
再之后就想到了域解析操作符"::",直接附上解决代码;
#include<bits/stdc++.h>using namespace std;int count=0;void fun(){printf("%d",++::count);}int main(){fun();}
问题完美解决,原因则是我们写代码的这个文件内也能看作是一个空间,所以name::
可以写为::
来获取当前的变量名;
附一图解决问题の图
C++11
这里来给大家(自己,博客访问量===0)介绍一下C++11的一个新标准;auto
,这个关键字C++98其实已经有了,只是有些多余且用的人极少~,C++98中auto
也叫做自动变量(拥有自动生命周期)
int a =10 ; //拥有自动生命期auto int b = 20 ;//拥有自动生命期static int c = 30 ;//延长了生命期
C++11中的auto可以根据声明变量时变量的初始值自动为此变量选择匹配的类型;这里也侧面说明了auto定义的变量必须在定义时初始化,这里与哪个关键字类似呀?
int a=10;auto auto_a=a;//自动判断类型,auto_a为int类型cout<<auto_a<<endl;//10cout<<typeid(auto_a<<endl; //int
笔者今天主要要介绍的是auto与for循环的结合使用,JavaScript、Python等众多语言都拥有类似于in of等用于循环的关键字,比起c++单调的for(int i=0 ;i<n;++i)
要舒服多了!
今天 笔者就告诉大家,C++也有了,哥咱家有钱了;
int a[10]={1,3,5,7,9,13,15};for(auto i:a){cout<<i<<"\t";}cout<<endl;
上述代码输出应该是什么呢?1 3 5 7 9 13 15 ?
不,其实是:1 3 5 7 9 13 15 0 0 0
要千万注意,这个智能变量会把这个数组从头到尾遍历一遍的;
此外还要注意auto
只是一个占位符,并不是一个真正的类型,不能使用一些以类型位操作数的操作符如typeid
与sizeof
;
cout << sizeof(auto) << endl;//错误cout << typeid(auto).name() << endl;//错误
命名空间
一个中大型软件往往由多名程序员共同开发,会使用大量的变量和函数,不可避免地会出现变量或函数的命名冲突。当所有人的代码都测试通过,没有问题时,将它们结合到一起就有可能会出现命名冲突。
例如小李和小航都参与了一个文件管理系统的开发,它们都定义了一个全局变量 fp,用来指明当前打开的文件,将他们的代码整合在一起编译时,很明显编译器会提示 p 重复定义(Redefinition)错误。
为了解决合作开发时的命名冲突问题,C++ 引入了**命名空间(Namespace)**的概念
namespace Li{ //小李的变量定义FILE fp = NULL;}namespace Hang{ //小韩的变量定义FILE fp = NULL}
namespace
是C++中的关键字,用来定义一个命名空间,里面可以包含变量、函数、类、typedef、#define等;
Li::fp = fopen("one.txt", "r"); //使用小李定义的变量 fpHan::fp = fopen("two.txt", "rb+"); //使用小韩定义的变量 fp
而使用命名空间/其中的变量需要用到``using`关键字;
using namespace Li;using Hang::fp
一个命名空间完整示例:
#include <stdio.h>//将类定义在命名空间中namespace Hang{class Student{public:char *name;int age;float score;public:void say(){printf("%s的年龄是 %d,成绩是 %f\n", name, age, score);}};}int main(){Diy::Student stu;stu.name = "小明";stu.age = 15;stu.score = 92.5f;stu.say();return 0;}
这里介绍的仅仅只是冰山一角,更多的内容还请读者自行探索(我也不会);