Cpp入门小知识一
相信大家刚接触c++的时候都会见到这2行代码。
#include<iostream>
using namespace std;
在大家的认识中可能是不管三七二十一写上这2行代码就对了,管它是什么呢。那这2行代码是什么意思呢,有什么用呢?
#include<iostream>可以理解为跟c语言中的#include<stdio.h>类似、等价的。是来告诉我们控制台来进行输入输出的,它是IO流。那using namespace std是干嘛的呢?
首先就要先了解一下其他东西。
在c语言中存在一个命名冲突的问题,命名冲突又是什么呢?在c语言中定义一个变量的名称,第一要符合变量名规范,第二不能跟关键字同名,但没有规定不能跟库函数的名字一样。rang在c语言中是用来生成随机数的。用它作为变量名会如何呢?
编译是通过了,要是包上了该函数的头文件呢?就不通过了,出现了重定义。
假如张三跟李四合作写一个项目,张三自己写了个头文件定义了个函数,李四在不知情的情况下定义了个变量跟张三的函数同样的名字,这不就起了命名冲突了吗。在c语言中是没有办法解决这个问题的,c++中引入了namespace用来解决这个问题的。
namespace是什么呢,是c++中的一个关键字,namespace叫命名空间,需要使用到这个关键字时候后面跟命名空间的名字,这个名字可以随便取,然后接一对{}即可,{}中即为命名
空间的成员。
在命名空间里定义rand这时候就编译通过了,但其结果怎么是一串很长的数字呢,其实打印的是它的函数指针,就是它的函数地址,只是以%d的格式打印,没有用%p打印。
如果我们定义一个变量跟函数,名字在同样的情况下是会报错。
同理我们命名空间里定义函数fun就不会报错。
最后如果我们定义了一个局部变量跟全局变量且是同名的情况下,会打印出0,因为局部变量优先于全局变量。
那咱就偏不打印局部变量的,而要让它打印全局变量的呢,这个好办,c++中有一个叫域作用限定符 :: ,只要在a的前面加上::就可以访问全局域。::a : : 前面是空白什么也没有,默认访问全局域里的a。
回到命名空间,如果要访问命名空间里的成员时,是不是也可以用到域作用限定符,答案是可以的。test::rand 意思是访问test命名空间域里面的成员rand。如果也想访问该命名空间里的其他成员也是一样的操作。
看到这里可能大家对命名空间到底是什么都还很懵逼,其实可以这样理解:namespace命名空间相当于是一个隔离空间,把变量、函数、类型关在这个隔离间里,与外界没有联系。我们在电视中可能会看到过这种情节,女方的老公因为做了犯法的事被抓去坐牢子,女方想要探望她老公的话会被带进去一个房间里面,里面有一个玻璃隔层,男方在那一边,女方在另一边,双方隔着一个玻璃层靠着电话在沟通。这种得靠着电话才能说话、互相听到彼此的声音的操作,就相当于可以用域作用限定符来访问命名空间里的成员一样。
namespace命名空间总结:
1、空间成员是可以定义变量、函数,类型的。
2、命名空间是可以嵌套的
3、如有存在多个相同名称的命名空间,编译器最后合并成一个命名空间里。
4、不能在函数内定义命名空间
要是一直得用域作用限定符才能使用命名空间里的东西话,那岂不是很繁琐很占用时间,有没有办法解决?
有的。可以用using namespace test; 这句代码的意思是把关在命名空间里的成员全部释放出来。这样就可以直接用这些成员了。
但要注意的是释放了命名空间的成员会引起冲突反而失去了命名空间的作用了。
换种方法:我们可以把需要经常使用到的成员单独释放出来,比如命名空间里的Add函数是我们要频繁使用的,可以单独释放出来。
using test::Add; 意思是单独释放命名空间里的Add成员。
现在知道C++中的using namespace std;是什么意思了吗,就是释放std库里面的成员。std是C++中标准库的命名空间。比如我们要用到的输入输出cin、cout就是定义在#include<iostream>这个头文件里面,如果没有用using namespace std来释放std命名空间的话,去使用则会出现未声明。
释放std全部成员后虽然可以直接使用了。但会存在风险。
那要是不全部释放std呢也是有办法使用的。可以用域作用限定符。
上面讲过释放命名空间里的全部成员的话会引起冲突,如果我们释放std里的全部成员,定义了一个叫cout的变量使用它就会报错。可以单独释放也可以用域作用限定符,命名空间的优势就体现出来了。
在我们日常练习中是可以全部释放的但会存在命名冲突的风险,所以在项目里我们去指定释放常用的。
输入输出
>> 流提取运算符
<< 流插入运算符
cin 标准输入流
cout 标准输出流
cin是用来输入的,cout是用来输出的。在c语言中的scanf,printf使用的时候需要控制它的格式会很繁琐,而cin、cout不需要控制格式了,自动识别类型,使用更便捷了。
#include<iostream>
using namespace std;
int main()
{
int a = 0;
int b = 0;
cout << "请输入a,b:";
//可以同时输入多个
cin >> a >> b;
cout << "a =" << a << " " << "b =" << b << endl; //endl是换行的意思
return 0;
}
缺省参数(也叫默认参数)
缺省参数是声明或定义函数时为函数的参数设置一个默认值。在调用该函数时,如果没有传指定实参的话则使用设置好的默认值,否则使用传过去的指定实参。
如果还不知道缺省参数是什么,这里举个例子:在男女感情交往的过程中,可能会存在这么种情况,女方面对一个自己不喜欢的异性表白,把他给拒绝了。但也不会拒绝这个异性对她的好,每逢节日必送礼、红包……照收不误,需要他时就找他,不需要时则把他晾在一旁。这或许就是传说中的“备胎”吧,突然有一天,这个女的有了男朋友,就不再去找这个“备胎了”。我们可以把缺省参数(默认参数)当成是“备胎”,而传过去的实参是男朋友,没有传实参的话我们就用这个“备胎”,如果有了实参,就晾着“备胎”不管了呗,用着男朋友就No problem了呀!!!
//设置默认参数值
void TestFun(int a = 10, int b = 10)
{
cout << "a=" << a <<" ";
cout << "b=" << b << endl;
}
int main()
{
//如有传实参则采用传过去的值
cout << "有传实参:";
TestFun(100, 200);
//如没有传实参则采用设置好的默认值
cout << "没传实参:";
TestFun();
return 0;
}
可能大家会想到该函数如有3个形参的话,只传一个、二个、多个实参呢?是可以的,但不能超过形参的个数。那可不可以跳过前一个,传实参给第二个呢?是不可以的。
缺省参数分类:
全缺省参数:就是全部都给了默认参数值就叫全缺省参数。
半缺省参数:就是部分没有设置默认参数值就叫半缺省参数。
那半缺省参数可不可以中间不给默认参数,两边给呢?不可以的
缺省参数应用场景:
在用c语言实现顺序表各个接口时写的初始化是写死了的,如在需要存入大量数据的情况下,默认开辟了3个空间大小是不够用的,需要重新扩容影响效率。在这种情况下使用缺省参数的话就会非常的好用。
//c语言初始化顺序表,写死了的
void SeqListInit(SeqList*p)
{
p->data = (SLDataType*)malloc(3 * sizeof(SLDataType)); //只开辟3个空间大小,如在存入大量数据的情况下空间会出现不够用,需要扩容会影响效率
if (p->data == NULL)
{
printf("开辟内存失败\n");
exit(-1);
}
p->size = 0; //把存储个数初始化为0
p->capacity = 3; //容量初始化为3
}
//c++ 加入缺省参数来实现初始化顺序表
void SeqListInit(SeqList*p,int n=3)
{
p->data = (SLDataType*)malloc(sizeof(SLDataType)*n); //开辟n个空间大小
if (p->data == NULL)
{
printf("开辟内存失败\n");
exit(-1);
}
p->size = 0; //把存储个数初始化为0
p->capacity = n; //容量初始化为n
}
int main()
{
SeqList s;
SeqListInit(&s); //在不知需要插入多少数据的情况下,使用默认参数
SeqListInit(&s,100); //如知道要一次性插入100个数据的时候,则可以传100进行内存开辟空间
return 0;
}
函数重载
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 顺序)必须不同,常用来处理实现功能类似数据类型不同的问题。
在c中实现一个Add函数的话,如该函数的参数类型是int,那就只能用int型的实参,要是想用其他类型的就得重新实现一个函数但又不能跟Add同名,那就得每次为同功能的函数其不同的名字岂不很烦吗。
然而在c++中可以支持同名函数来实现功能类似的函数。
重载要求:函数重载是看参数个数、类型、顺序(形参类型顺序)的不同,不是看返回值不同。
#include<iostream>
using namespace std;
//函数重载来实现不同类型的数据
int Add(int num1, int num2)
{
return num1 + num2;
}
double Add(double num1, double num2)
{
return num1 + num2;
}
double Add(int num1, double num2)
{
return num1 + num2;
}
//函数重载是看类型不同跟类型顺序不同的
double Add(double num2,int num1)
{
return num1 + num2;
}
int main()
{
cout<<Add(1,1)<<endl;
cout << Add(2.2, 2.2)<<endl;
cout << Add(1, 2.2)<<endl;
return 0;
}
CSDN-Ada助手: 恭喜您写了第16篇博客!看了您关于“lv_event_get_current_target_obj”的理解,收获颇丰。希望您能继续保持创作的热情和劲头,不断分享您的心得体会。下一步建议可以尝试深入探讨lvgl中其他函数或特性的用法,或者分享一些实际项目中的应用经验,相信会给读者带来更多启发和帮助。期待您更多精彩的分享!
顾小兔子乖乖: 来了老弟
老菜园的小嫩芽: 写的好好