初识c++(一)

本文详细介绍了C++中的命名空间解决命名冲突,如何使用标准库,包括缺省参数、函数重载和引用的深入理解。特别强调了常引用和传引用的区别,并通过实例演示了关键概念和实践应用。

c++关键字

c语言中一共有32个关键字,c++一共有63个关键字
在这里插入图片描述
这里只是初步做一个了解,等以后见到了,会具体展开的讲。

命名空间

c语言命名冲突问题

我们先来看一个代码
在这里插入图片描述
在c/c++语言中,会先从离代码最近的地方进行查找(先局部后全局),虽然有一个函数scanf但是由于int scanf离代码最近,所以编译器并不会把scanf当作函数。这就造成了错误。且c语言不能实现scanf和scanf变量一起达成正确使用的目的,所以c++有了一个好的解决办法。

命名空间

为了弥补c语言的缺陷,c++引入了命名空间namespace的定义,要想解决冲突问题,只能使用命名空间,命名空间实际上是一个域。
如果想要实现不同的功能,指出来源即可,其中std就是一个域,c++把所有库表示符的名字都放在了std这个命名空间里面。
在这里插入图片描述

命名空间的定义

定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。

//1. 普通的命名空间
namespace N1 // N1为命名空间的名称
{
 // 命名空间中的内容,既可以定义变量,也可以定义函数
 int a;
 int Add(int left, int right)
 {
 return left + right;
 }
}
//2. 命名空间可以嵌套
namespace N2
{
 int a;
 int b;
 int Add(int left, int right)
 {
 return left + right;
 }
 
 namespace N3
 {
 int c;
 int d;
 int Sub(int left, int right)
 {
 return left - right;
 }
 }
}
//3. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
namespace N1
{
 int Mul(int left, int right)
 {
 return left * right;
 }
}

标准库的使用

我们要使用标准库内的东西,有三种方式
(1)指定命名空间,比较麻烦,每个地方都要指定,但是他是最规范的方式。上图就是第一种方式

int main()
{
 printf("%d\n", N::a);
 return 0; 
}

(2)把std整个展开相当于库里面的东西都到全局域里了,看起来也方便了不少,但是如果我们自己定义的东西和库冲突就没办法解决了,我们为了图方便,平日里日常练习用的就是这种方式。

using namespce N;
int main()
{
 printf("%d\n", N::a);
 printf("%d\n", b);
 Add(10, 20);
 return 0; 
}

(3)对常用的库里面的东西展开,以后做项目经常用这种方式,这种方式是方式一和方式二的折中办法

using N::b;
int main()
{
 printf("%d\n", N::a);
 printf("%d\n", b);
 return 0; 
}

缺省参数

缺省参数的概念

缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参。

void TestFunc(int a = 0) {
 cout<<a<<endl; }
int main()
{
 TestFunc(); // 没有传参时,使用参数的默认值
 TestFunc(10); // 传参时,使用指定的实参
}

缺省参数分类

全缺省参数

void TestFunc(int a = 10, int b = 20, int c = 30) {
 cout<<"a = "<<a<<endl;
 cout<<"b = "<<b<<endl;
 cout<<"c = "<<c<<endl; }

半缺省参数

void TestFunc(int a, int b = 10, int c = 20) {
 cout<<"a = "<<a<<endl;
 cout<<"b = "<<b<<endl;
 cout<<"c = "<<c<<endl; }

需要注意的是

  1. 半缺省参数必须从右往左依次来给出,不能间隔着给
  2. 缺省参数不能在函数声明和定义中同时出现,最好声明给缺省,但是定义不给。
    在这里插入图片描述
//a.h
void TestFunc(int a = 10);
// a.c
void TestFunc(int a = 20)
{}
// 注意:如果生命与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那
个缺省值。

3.缺省值必须是常量或者全局变量
4.c语言不能使用缺省参数

函数重载

函数重载定义

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 顺序)必须不同,常用来处理实现功能类似数据类型不同的问题

int Add(int left, int right) {
     return left+right; 
 }
double Add(double left, double right) {
     return left+right; 
 }
long Add(long left, long right) {
     return left+right; 
 }
int main()
{
   Add(10, 20);
   Add(10.0, 20.0);
   Add(10L, 20L);
   return 0; 
 }

要构成函数重载只能参数类型不同,或者参数个数不同,其余都不叫函数重载

问:下面这两个函数构成函数重载吗

short Add(short left, short right) {
   return left+right; 
}
int Add(short left, short right) {
    return left+right;
}

显然是构不成的因为这两个函数参数个数、类型都相同。不满足构成重载函数的条件

问:这两个函数是重载吗?
在这里插入图片描述

根据条件,这两个函数参数个数不同,所以构成重载,但是却会发生冲突。至于为什么大家可以自行去编译器试试(提示:f(1,2)到底会调用哪个函数呢?)不明确所以构成冲突

引用(别名)

引用的概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
公式:类型& 引用变量名(对象名) = 引用实体;

void TestRef()
{
 int a = 10;
 int& ra = a;//<====定义引用类型
 
 printf("%p\n", &a);
 printf("%p\n", &ra);
}

引用的特性

  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,再不能引用其他实体

void TestRef()
{
int a = 10;
// int& ra; // 该条语句编译时会出错
int& ra = a;
int& rra = a;
printf(“%p %p %p\n”, &a, &ra, &rra);
}

(超重点)常引用

void TestConstRef()
{
 const int a = 10;
 //int& ra = a; // 该语句编译时会出错,a为常量
 const int& ra = a;
 // int& b = 10; // 该语句编译时会出错,b为常量
 const int& b = 10;
 double d = 12.34;
 //int& rd = d; // 该语句编译时会出错,类型不同
 const int& rd = d; 
 }

在这里插入图片描述
在这里插入图片描述
大家思考一下这两个哪个对,哪个错,思考玩接着往下看。
答案:一错二对。原因就是因为a原本就是一个常变量,如果用int&就那么ra(a的别名就不具有常性了(可以修改)),那么就说明ra的权限大于原本的a了,那是万万不行的。
请大家务必记住下面这个图

在这里插入图片描述
大家继续思考下面这个代码,哪个引用才是对的呢?

int c=0;
double &rc=c;
const double &rc=c;

提示(隐式转换和强制转换一样会产生一个临时变量,且临时变量具有常性)
答案2才是对的,原因就是这个代码明显发生了隐式转换,c要转化成临时的double类型的变量,所以这里引用的对象应该的这个double类型的临时变量,而临时变量具有常性。所以应该用第二种方法引用。大家明白了吗?
在这里插入图片描述
如何证明呢?大家看看下面这个图
在这里插入图片描述

传值返回

函数传值返回返回的是返回对象的临时拷贝
在这里插入图片描述
在这里插入图片描述
由于c返回的是临时变量具有常性,所以要加const,且引用和c的地址并不相同,而是和临时变量地址相同。

传引用返回

函数传引用返回返回的是返回对象的引用

在这里插入图片描述
大家看看上面的题输出什么?答案其实是12。请思考后接着往下看
由于返回的是引用,就是返回了函数变量c的别名,ret和c的地址是一模一样的,由于第一次调用后会销毁栈帧,在此地址上存了一个值3,如果再次调用,会在相同的位置(c的地址处)也就是c的地址上再次覆盖12,由于两次调用储存数据的地址是一模一样的,所以会输出12。

未完待续

这篇就到这里,还有一部分分别是内联函数,atuo,和范围for的使用,下篇接着写

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeApe_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值