C++入门
c++是对于c语言的补充而发展的一种面向对象的语言,也能兼容c语言的内容,所以c语言的东西可以在cpp文件中写c语言的内容,也是可以运行的(可以混写)
文章目录
- C++入门
- 命名空间
- 命名空间的定义
- 命名空间的使用
- C++的输入和输出
- 缺省函数
- 缺省函数的概念
- 函数重载
命名空间
namespace是为了防止命名重复然后会报错的问题,而提出的一种新型的方式来解决命名冲突问题。使用命名空间的目的是对于标识符的名称进行本地化,以免命名冲突或者名字污染。
//比如这个例子
int a=0;
namespace why{
int a=1;//namespace 是命名空间操作符,表明我们规定了一个命名空间why,里面是有一个变量a为1
};
int main()
{
a=10;
cout<<a<<" "<<endl;//
return 0;
}
命名空间的定义
定义命名空间,需要使用namespace这个关键字,然后加上命名空间的名字,最后加上一对{},这就是完整的命名空间
namespace why{
int data=0; //可以定义变量
void Print();//命名空间里面可以定义可以声明函数
int Add(int x,int y){
return x+y;
}
}
//这就是完整且正确的定义
/
//命名空间是可以嵌套的,命名空间内部是可以再定义命名空间的
namespace why {
int a = 1;//namespace 是命名空间操作符,表明我们规定了一个命名空间why,里面是有一个变量a为1
namespace cdd {
int a = 10;
}
};
using namespace why;
int main()
{
//a = 10;
cout << why::cdd::a << " " << endl;//
return 0;
}
C++中的namespace是允许同一个工程存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中
//比如下文在test.cpp中
#include "test.h"
using namespace std;
namespace name1 {
int data=1;
namespace name2 {
int data = 10;
}
void Print()
{
cout << "hello,world!!!" << endl;
}
}
int main()
{
name1::Set();
name1::Print();
return 0;
}
//下文为test.h
#include<iostream>
using namespace std;
namespace name1 {
void Set() {
cout << "Set!!!" << endl;
}
}
//也就是说,我们在最后链接的过程中将两个相同名称的命名空间里面的成员合并在一起。
//一个命名空间就定义了一个新的作用域,命名空间中的所有内容都是局限于该命名空间中
命名空间的使用
命名空间的使用,大致有三种方式
//初始化一个命名空间为why
namespace why{
int data=0;
}
//1.加命名空间名称及其作用域限定符
int main()
{
cout<<why::data<<endl;
return 0;
}
//2.使用using将命名空间中的某一个成员引入
using why::data;
int main()
{
cout<<why::data<<endl;
return 0;
}
//3.using namespace 命名空间名字 的引入
using namespace why;
int main()
{
cout<<why::data<<endl;
return 0;
}
以上三种方法,就是对于命名空间的使用方法
std,实际上就是C++的标准库,里面包括STL,C++库等等,当我们使用using namespace std展开的时候,大部分的函数都能使用了
C++的输入和输出
这个地方可以直接看下面代码演示
#include<iostream>
using namespace std;
int main()
{
int a;
cin >> a; //cin输入,自动识别a的类型
cout << a << endl; //自动输出a,但是如果为double 且需要精确到XX位小数,(一般)就不用cout,需要使用 printf("%.2f",double);
return 0;
}//cin 是输入 cout是输出 endl是换行 相当于<<"\n";
std命名空间的使用规范
std是C++标准库的命名空间,如何展开std使用更合理呢?
- 在日常练习中,建议直接using namespace std即可,这样就很方便。
- using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对
象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模
大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 +
using std::cout展开常用的库对象/类型等方式。
缺省函数
缺省函数的使用,是相较于C语言,比较神奇的一种函数的使用方式,比较灵活多变
缺省函数的概念
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实
参则采用该形参的缺省值,否则使用指定的实参。
#include<iostream>
using namespace std;
void Print(int x=10){
cout<<x<<endl;
}
int main()
{
Print(20);//这样输出为20 有参数传参的时候,使用传参值
Print();//这样输出为10 没有传参的时候,使用参数的默认值
return 0;
}
缺省函数分类
- 全缺省函数
#include<iostream> using namespace std; void Print(int x=10,int y=20){ cout<<x<<" "<<y<<endl; } int main() { Print(20);//这样20传递给了x 然后输出为20 20 Print();//这样没有实参传值,那就是输出为 10 20 return 0; }
- 半缺省函数
#include<iostream> using namespace std; void Print(int x,int y=20){ //这样x是必须要接受数值 cout<<x<<" "<<y<<endl; } int main() { Print(20);//这样20传递给了x 然后输出为20 20 Print();//这样没有实参传值,因为是半缺省,x没有传递数值所以会报错 return 0; }
全缺省函数,无所谓传参不传参,如果是不传参,那就是说,直接使用原始值既可以,传参的话,就是将参数替换函数的原始形参值,即可,但是传参是一一对应的
半缺省函数,必须将没有原始数值的参数,进行传参,且没有原始数值的参数从左向右一依次没有,不能跳过
#include<iostream> using namespace std; void Print(int x,int y=20,int z=10){ //这样x是必须要接受数值 cout<<x<<" "<<y<<endl; } //Print是缺省函数,可以这样int x,int y=20,int z=10; //但是不能这样 int x=10,int y,int z=10; int main() { Print(20);//这样20传递给了x 然后输出为20 20 Print();//这样没有实参传值,因为是半缺省,x没有传递数值所以会报错 return 0; }
半缺省参数必须从右往左依次来给出,不能间隔着给
缺省参数不能在函数声明和定义中同时出现
//test.h void Func(int a, int b, int c = 20);//在头文件中声明 //test.cpp void Func(int a, int b, int c)//在cpp源文件中定义 { cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl; } //这样会报错,显示cpp文件的Func重定义默认参数,也就是说在cpp文件中的c参数是重复定义为20,如果我们将20删除 改为int c 这个的话,就不会报错 //也就是说,缺省函数不能将定义和声明分开 int main() { Func(10,20); return 0; } // //注意:如果生命与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值。 //test.h void a(int a=10) { } //test.cpp void a(int a=20){ } //这样的话会进行报错,这也就是当头文件中对函数使用缺省函数时,cpp文件中不能再用这个缺省,得改成一般函数,不然编译器报错
上述程序调用流程图
- 从main函数中,想要调用Func函数,这个时候先去.h文件去找到声明,然后发现Func为一个缺省函数,最少赋值前两个ab即可,那么就会调用.cpp文件中Func的定义,传入abc的数值,c的数值就为20
- 注意:如果生命与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值。
函数重载
函数重载实际上就是,将同一个函数名,经过变一下参数的个数、类型、顺序等使得这两个函数不一致,在cpp中称为函数的重载
函数重载不根据返回值类型来判断,也就是int和double作为返回值时,如果函数名以及参数完全相同,这不是重载
//函数重载的样例
//正确样例
//1.改变参数类型,只要下面参数有不同的类型即可
void Func(double a, int b, int c)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}
void Func(int a, int b, int c)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}
//2.改变参数顺序 先double 在int 和 先int 再double
void Func(double a, int b, int c)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}
void Func(int a, double b, int c)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}
//3.改变参数个数
void Func(int a, int b, int c)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}
void Func(int a)
{
cout << "a = " << a << endl;
}
//以上是正确样例
///
//下面是错误样例
void Func(int a, int b, int c)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}
double Func(int a, int b, int c)
{
cout << "a = " << a << endl;
}//只是改变返回类型,这不是重载,因为重载不管这个返回值类型为什么,只关心参数是不是完全一样,不一样(个数,顺序....),那就是重载,反之,不是重载
函数重载的原因:C++中支持函数重载,是因为进行了名字修饰
名字修饰就是在编译之后,通过参数是否不同,给定不一样的汇编后的名字,这样的话,我们就可以根据不同的名字去call不同的函数,这就实现了函数从重载在不同的编译器环境下,不同的重载函数命名规则
程序运行要经历这四个阶段:预处理、编译、汇编、链接
预处理:头文件展开/宏替换/条件编译/去掉注释等等 得到.i文件
编译:检查语法,生成汇编代码。 得到.s文件
汇编:汇编代码转换成二进制代码。 得到.o文件
链接:将这些代码链接起来,也就实现了多文件的交互 得到.exe可执行程序文件 or .out文件