欢迎来到本期节目- -
C++入门基础
入门必备
- [命名空间- - namespace](#命名空间- - namespace)
- c++输入&输出
- 缺省参数
- 函数重载
- 引用
- const引用
- [内联函数- - inline](#内联函数- - inline)
- nullptr关键字
命名空间- - namespace
本质:
|------------------------------|
| 命名空间是一个域,是对作用域的特殊抽象。 |
| 在c++中,域有函数局部域,全局域,类域以及命名空间域。 |
作用:
|-------------------------------------------|
| 解决命名冲突的问题 |
| 由于编译时,编译器按照语法查找(变量/函数)的声明或定义的出处时, |
| 在同一个域不能出现相同标识符,所以命名空间域,起到了域隔离的作用,解决了命名冲突。 |
应用:
++namesapce关键字,后面跟该域的名称(标识符),然后跟{}++
cpp
namespace my_room
{
int var; //变量
void func()//函数
{
//....
}
class A //类
{
public:
A()
{
//....
}
private:
char ch;
}
namespace nested_room //命名空间
{
//....
}
}
小知识
|---------------------|
| 命名空间域和类域不影响变量的生命周期。 |
注意事项
- 命名空间只能定义在全局或者嵌套;
- 在同一个域(全局域,命名空间域)或者多文件中,同名的namespace可以认为是一个命名空间域;
- 但是在不同的域中(既嵌套的namespace),同名的namespace是不同的命名空间域;
例如:
cpp
#include<iostream>
using namespace std;
namespace my_room
{
void print1()
{
cout<<"my_room::print1()"<<endl;
}
namespace my_room //该命名空间域和外层的my_room没有命名冲突,只是受到了外层的命名空间域的限制,是独立的域
{
void print1()
{
cout<<"my_room::my_room::print1()"<<endl;
}
}
}
namespace my_room //该命名空间域与上方最外层的my_room在同一全局域,又名称相同,既在同一命名空间域,相当于把print2()函数定义在上方的my_room。
{
void print2()
{
cout<<"my_room::print2()"<<endl;
}
}
|----------------|
| 如何使用命名空间域中的成员? |
- 指定方式
- 通过 ++作用域操作符++ : : 指定成员
cpp
#include<iostream>
namespace my_room
{
int a = 1;
void print()
{
printf("hihihi\n");
}
}
int main()
{
int a = 10;
printf("%d\n", a);
printf("%d\n", my_room::a);
my_room::print();
return 0;
}
输出结果:
cpp
10
1
hihihi
-
展开方式
-
使用using关键字
- 展开个别命名空间成员
- 展开整个命名空间
-
cpp
#include<iostream>
namespace my_room
{
int a = 1;
void print()
{
printf("hihihi\n");
}
}
using my_room::a; //相当于将a的作用域延伸到了全局域
int main()
{
printf("%d\n",a);
printf("%d\n",my_room::a);
return 0;
}
输出结果:
cpp
1
1
cpp
#include<iostream>
namespace my_room
{
int a = 1;
void print()
{
printf("hihihi\n");
}
}
using namespace my_room; //展开整个命名空间
int main()
{
printf("%d\n",a);
print();
return 0;
}
输出结果:
cpp
1
hihihi
c++输入&输出
|---------------------------------------------|
| <*iostream>*是c++标准的输入/输出流库,std是该标准库的命名空间。 |
|--------------------------------------|
| std::cin是istream类的对象,主要面向窄字符的标准输入流。 |
| std::cout是ostream类的对象,主要面向窄字符的标准输出流。 |
|-------------------------|
| <<流插入运算符,一般练习中通常用于输出; |
| >>流提取运算符,一般练习通常用于输入。 |
|---------------------------------------|
| std::endl是一个函数,流插入输出时相当于一个换行符加上刷新缓冲区。 |
|------------------------------|
| c++流插入和流提取可以通过函数重载,自动识别变量类型。 |
缺省参数
拥有缺省参数的函数在声明和定义分离时,规定必须函数声明给缺省值。
定义:
|-----------------------------|
| 缺省参数是函数声明或定义时为函数的形参指定一个缺省值。 |
| 在调用该函数时,若没有指定实参,则使用该缺省值。 |
分类:
- 全缺省参数
- 全部形参给缺省值。
- 半缺省参数
- 部分形参给缺省值
注意事项:
- 缺省参数只能从右往左依次给定。
- 函数调用时的实参只能从左往右依次给定。
函数重载
定义:
|------------------------------------|
| c++支持在同一作用域中,出现同名函数,但是要求同名函数的形参不同。 |
构成函数重载的条件:
- 同一作用域
- 相同函数名
- 形参类型 或 形参类型顺序 或 形参个数 不同
栗1:
cpp
#include<iostream>
int add(int a, int b)
{
return a+b;
}
float add(float a, float b)
{
return a+b;
}
|-------------------------------|
| 在同一域中,同名的add函数的形参类型不同,构成函数重载。 |
栗2:
cpp
#include<iostream>
using namespace std;
void func(int x,double y)
{
cout<<"func(int x,double y)"<<endl;
}
void func(double y,int x)
{
cout<<"func(double y,int x)"<<endl;
}
|----------------------------------|
| 在同一域中,同名的func函数的形参类型顺序不同,构成函数重载。 |
栗3:
cpp
#include<iostream>
using namespace std;
void pear()
{
cout<<"hehe"<<endl;
}
void pear(int m)
{
cout<<"haha"<<endl;
}
|--------------------------------|
| 在同一域中,同名的pear函数的形参个数不同,构成函数重载。 |
注意事项:
- 如果void pear(int m){}给了缺省值,依然构成函数重载,但是存在调用歧义。
引用
定义:
|--------------------------------------------------------|
| 引用是给一个已经存在的变量取了一个别名,编译器不会为引用变量开辟内存空间,引用和引用对象共用同一块内存空间。 |
格式:
|-------------------|
| 类型& 引用别名 = 引用对象; |
cpp
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int& b = a;
cout<< &a <<endl;
cout<< &b <<endl;
return 0;
}
输出结果:
cpp
0104FCA0
0104FCA0
引用的特性:
-
引用必须初始化
-
引用一旦引用一个实体,就不能引用其它实体(不能改变指向)
-
一个实体可以有多个引用
cpp
int main()
{
int val = 10;
int& a = val;
int& b = val;
int& c = b; //a,b,c都是val的引用
return 0;
}
const引用
c++中,引用和指针的访问权限,只能缩小不能放大。
-
const引用不仅可以引用const对象,还可以引用普通对象,这是访问权限的缩小,
-
但是普通引用不能引用const对象,不能实现权限放大。
注意:
- 引用的权限缩小,对引用对象本身没有影响。
cpp
int main()
{
int val = 10;
const int& b = val; //虽然不能通过b修改数据,但是可以通过val修改数据。
val = 30; //这里val一改,b也跟着改了---因为是同一块空间
return 0;
}
从以上可以得出结论,const引用真是够花心的,不仅有普通对象,还有const对象,
这样的const引用,会有人喜欢吗?别说,在临时对象眼中,const引用就是唯一。
(冷笑话)
临时对象:
|------------------------------|
| 编译器需要表达式的求值结果而临时创建的一个未命名的对象。 |
|-------------------|
| 那么具体什么时候会创建临时对象呢? |
- 表达式求值
- 类型转换
- 传值返回
cpp
int add(int x,int y)
{
int z = x+y;
return z;
}
int main()
{
const int& a = 4*5;//表达式求值,需要临时对象存储结果
const double& b = a;//类型转换,需要临时对象存储中间值
const int& ret = add(1,2);//函数返回的是临时对象
return 0;
}
小知识
|------------------------------|
| c++规定临时对象具有常性,所以只能使用const引用。 |
|----------------------------------|
| 引用和指针有一样的权限缩小放大问题,那么两者之间到底有什么区别? |
指针 | 引用 |
---|---|
创建时开辟空间 | 语法上不开空间 |
语法上不必初始化 | 语法上必须初始化 |
间接访问对象 | 直接访问对象 |
可以改变指向 | 不能改变指向 |
sizeof大小是地址大小 | sizeof大小是对象大小 |
空/野指针较多 | 空引用较少 |
内联函数- - inline
作用:
- c++编译器会在调用该函数的地方将其展开,减少了函数栈帧的开销,提高效率。
- 替代宏替换
注意事项:
- inline关键字对编译器来说只是建议,不一定会展开,只适合++代码简短,频繁调用++的函数。
- inline函数的声明和定义不建议分离,会导致链接错误。因为展开意味着没有函数地址。
nullptr关键字
|---------------------------------------------------|
| c++中,nullptr是一个特殊的关键字,它可以转换成任意类型的指针,相当于c语言中的NULL, |
| 而c++中的NULL,是整型0的宏替换。 |
cpp
//<stddef.h>
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
希望该片文章对您有帮助,请点赞支持一下吧😘💕