目录
- C++的简单介绍
- 命名空间
- 命名空间的使用
- C++的输入与输出
- 缺省参数
- 函数重载
C++的简单介绍
本贾尼·斯特劳斯特卢普博士在C的基础上增加了面向对象的特性,这时又增加了继承和、类、封装的概念,为后来的面向对象的编程奠定了基础,这被命名为C++
命名空间
1.定义命名空间,需要关键字namespace,namespace后面跟命名空间的名字,后接一对{ },{ }中即为命名空间中的成员,命名空间可以定义变量/函数/类型等。
namespace rzj
{
//变量
int a = 2;
//函数
int Add(int a, int b)
{
return a + b;
}
//结构体
struct listnode
{
struct node* c;
int val;
}LN;
}
2.namespace 本质上是定义一个域,这个域和全局域各自独立,不同的域可以定义同名的变量。
:: 域作用限定符:下面的用例中有说明
#include<stdio.h>
#include<stdlib.h>
namespace rzj
{
int rand = 2;
}
int a = 0;
int rand = 2;
int main()
{
//这个会和stdlib.h下的rand函数产生冲突
printf("%p\n",rand);
//rand访问的是全局域中的stdlib.h下的函数指针
//默认先访问局部的域再访问全局的域
printf("%d\n",rzj::rand);//2
// 命名空间的名字::命名空间中的成员名
int a = 1;
printf("%d\n", a);//1
//全局域上和局部域上出现两个相同的变量,就近原则,先访问局部域
//:: 域作用限定符
printf("%d\n",::a);//0
//:: 前面什么都没有,默认访问全局域
return 0;
}
int main()
{
printf("%d\n", rzj::Add(1, 1));
//函数的命名空间的访问
struct rzj::Node p1;
//结构体的命名空间访问,访问的是名字,不是关键字
return 0;
}
3.C++域中有全局域、局部域、命名空间域、类域,域影响的是编译是语法查找一个变量/函数/类型出处(声明或定义)的逻辑,有了域隔离,名字冲突就解决了。
局部域和全局域既影响编译时查找,又影响变量的生命周期,命名空间域和类域不影响变量的生命周期,只影响编译时查找。
4.namespace只能定义在全局,当然也可以嵌套定义。
namespace a
{
namespace b
{
int rand = 1;
int Add(int a, int b)
{
return a + b;
}
}
namespace c
{
int rand = 2;
int Add(int a, int b)
{
return a * b;
}
}
}
int main()
{
printf("%d\n", a::b::rand);//1
printf("%d\n", a::c::rand);//2
return 0;
}
5.多文件中可以定义同名的namespace,他们默认合并在一起,就像同一个namespace一样,是逻辑上的合并,并不是真的合并。
stack.h
namespace rzj
{
//...
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
}
stack.c
namespace rzj
{
//...
}
test.c
int main
{
//调用rzj namespace的
rzj::ST st2;
//访问结构体的命名空间
printf("%d\n", sizeof(st2));
rzj::STInit(&st2, 4);
rzj::STPush(&st2, 1);
rzj::STPush(&st2, 2);
}
6. C++标准库放在一个命名空间std中
命名空间的使用
命名空间的使用有三种方式:
1.using namespace rzj; 把命名空间全部展开
全部展开在自己写的程序下可以用,但是在公司开发中用会产生冲突。
2.指定命名空间中的成员
经常使用这个成员就把它展开来
rzj::a;
每个成员都指定比较麻烦
3.展开命名空间中某个成员
using rzj::b;
公司开发过程中常用的是2 和 3
namespace rzj
{
int a = 2;
int b = 1;
}
using namespace rzj;
//展开命名空间
using rzj::b;
//展开命名空间中某个成员
int main()
{
printf("%d\n",b);
printf("%d\n",b);
printf("%d\n",b);
printf("%d\n",rzj::a);
//指定访问
return 0;
}
C++的输入与输出
1.是标准的输入输出流的库,定义了标准的输入输出流的面向对象。
2.std::cin是istream类的对象,面对窄字符的标准输入流
3.std::cout是ostream类的对象,面对窄字符的标准输出流
4.<<是流插入运算符, 输出流,>>是流提取运算符,输入流(C语言中是左移和右移操作符)
5.std::endl(endl == end line)一个字符的结束或者换行
endl是一个函数,流插入输出时相当于1个换行
6.C++的输入输出时可以支持自定义类型,并且可以自动识别变量的类型。
#include<iostream>
using namespace std;
int main()
{
int a, b, c;
cin >> a >> b >> c;
//1 2 3
cout << a << " " << b << " " << c << endl;
//1 2 3
return 0;
}
缺省参数
1.在调用函数时,如果没有传参时,使用参数的默认值,也就是缺省值,传了参数时,使用指定的实参
2.全缺省:在形参中,都给了缺省值
半缺省:在形参中,给了部分缺省值
3.C++规定半缺省给的值,必须从右往左连续缺省,不能间隔和跳跃给缺省值
4.有缺省函数的调用,传参时,实参必须从左往右给,不能间隔,跳跃
5.在声明和定义时,在声明中给缺省值,声明在.h文件中,在定义中不给缺省值,定义在.c文件中,为了防止冲突
缺省参数的意义:在开空间时提前给缺省值,可以防止空间的浪费,提前知道要1000个int大小的空间,就提前给实参1000,传给缺省参数
void Func(int a = 0)
{
cout << a << endl;
}
int main()
{
Func();
// 没有传参时,使⽤参数的默认值
Func(10);
// 传参时,使⽤指定的实参
return 0;
}
// 全缺省
void Func1(int a = 10, int b = 20, int c = 30)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl << endl;
}
// 半缺省
void Func2(int a, int b = 10, int c = 20)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl << endl;
}
函数重载
C++允许在同一作用域中出现同名函数,但要求这些同名函数的形参不同,可以是参数个数不同或者类型不同
这是构成函数重载的条件。
函数的返回值不同不构成重载
// 1、参数类型不同
int Add(int left, int right)
{
cout << "int Add(int left, int right)" << endl;
return left + right;
}
double Add(double left, double right)
{
cout << "double Add(double left, double right)" << endl;
return left + right;
}
// 2、参数个数不同
void f()
{
cout << "f()" << endl;
}
void f(int a)
{
cout << "f(int a)" << endl;
}
// 3、参数类型顺序不同
//其实就是参数的类型不同
void f(int a, char b)
{
cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
cout << "f(char b, int a)" << endl;
}
// 下⾯两个函数构成重载
// f()但是调⽤时,会报错,存在歧义,编译器不知道调⽤谁
//解决办法是把第一个f1封装到一个命名空间中去,第一个调用时是对命名空间的成员进行调用,第二个是在全局域中调用
//但是这种办法也违背了他们不是函数重载了,因为函数重载是在同一个作用域中才可以实现,所以这个是没有解决办法的
//无参
void f1()
{
cout << "f()" << endl;
}
//不传参时是无参,会存在歧义
void f1(int a = 10)
{
cout << "f(int a)" << endl;
}