1.介绍c++
C++头文件风格
c++ 老风格:以.h结尾 是c语言风格 stdio.h (尽量不)
c++的转换风格: 去掉.h 在文件名前加c 例如#include
c++ 新风格 :没有拓展名 直接文件名,#include
2.c++ 的开发环境
1. visual studio 2018
2. qt creator 5.3
3. g++ 开发环境
第一步.安装g++ ,sudo apt-get install g++
第二步. 编写.cpp的代码
第三步: g++ xxx.cpp -o abc
3.基本输入输出
1. 标准输出 cout
格式: cout << "字符串" << 变量 << 变量 << endl;
注意: endl是换行,可以放中间和末尾
c++的输出是流的方式实现是(stream)
在定义对象时,系统会在内存中开辟一段缓存,用来存放输入输出流的数据,缓冲区满或者遇到endl后或者flush后才会输出。
需要头文件 #include
cout是一个变量(是输出流的对象)
2.格式化输出 (不是重点)
第一种方式: setf成员函数,cout的成员函数。
fmtflags setf(fmtflags __fmtfl)
作用: 对输出的内容做格式化处理
参数: __fmtfl 是需要格式化处理的状态
比如: ios_base::showbase 显示进制的前缀
fmtflags setf(fmtflags __fmtfl, fmtflags __mask)
作用: 对输出的内容做格式化处理
参数: __fmtfl 是需要格式化处理的状态
__mask 需要取消的状态位
案例:cout. setf(ios_base::hex,ios_base::basefield);
综合案例: 设置宽度 和设置对齐方式
cout.width(宽度);
设置右对齐方式 (setf函数,需要使用两个参数的版本,第一个参数ios_base::right,第二个参数是 ios_base::adjustfield )
第二种方式: cout的成员函数 例如 width( )
第三种方式:setiosflags函数 ( 笔记的方式发给大家--自行学习)
setiosflags 是包含在命名空间iomanip 中的C++ 操作符,该操作符的作用是执行由有参数指定。
区域内的动作;
3.标准输入
关键字:cin
格式: cin >> 变量1 >> 变量2 ;
注意: cin也是一个对象,暂时理解成结构体变量
等价于 scanf
不可以加字符串 endl
cin可以识别基本数据类型。int double float short long
输入两个整形,计算他们的模,输出。
4.标准错误
关键字:cerr
格式:cerr << "字符串" << 变量 <
一般是遇到错误,需要立马打印出来的场景
5.标准日志:
关键字: clog
格 式: clog << "字符串" << 变量 <
需要打印日志的时候需要
代码:
- #include<iostream>
- #include<cstdio>
- using namespace std;
- int main()
- {
- int c;
- cout<< "我的名字:"<<"she001"<<endl<<"今年:18岁"<< endl;
- int x=0x123;
- //cout.setf(ios_base::hex,ios_base::basefield);//设置输出为十六进制
- //cout.setf(ios_base::oct,ios_base::basefield);//设置输出为八进制
- //cout.setf(ios_base::dec,ios_base::basefield);//设置输出为十进制
- //cout.setf(ios_base::showbase);//设置为标准输出,加上 0x
- //cout<<"x="<<x<<endl;//标准输入
-
- //cout.width(10);//设置输出的数据 宽度为10
- //cout.setf(ios_base::right,ios_base::adjustfield);//设置右对齐
- //cout<<x<<endl;
-
- ///标准输入 展示理解为结构体变量
- //关键字: cin
- //注意 : cin 也是一个对象
- //等价于scanf
- //cin 可以识别基本数据类型 int double float short long
- //
- //
- //
- // 练习 输入两个变量 取膜
-
- //int a,b;
- // cin>>a>>b;
- // int d= a%b;
- // cout<<d<<endl;
- //
-
-
-
-
- ///标准错误
- //关键字:cerr
- //格式:cerr <<"字符串"<<"变量"<<endl;
- //无缓冲
- cerr<<"我的错误"<<x<<endl;
-
-
- //标准日志
- //关键字 clog
- //格式 clog<< " 字符串"<<"变量"<<endl;
- //注意 :有缓冲 和cout 的使用一样 .
- // 打印的时侯需要
-
- //clog<<"casda"<<x<<endl;
-
-
-
- return 0;
- }
4.名字空间
1. 前奏: using namespace std; 名字空间std
为什么要名字空间;
防止命名冲突,提供作用域。
模块化编程,提高效率
2.定义名字空间
格式:namespace 名字空间名 { 定义变量; 定义函数;};
注意: 在同一个作用域内,不可以有相同的名字空间名
3.名字空间可以使用的内容
可以定义变量
可以定义结构体
可以定义常量
可以定义函数
可以定义名字空间
可以定义枚举
4.案例
namespace huaqing{
int danny = 12;
const long num = 20;
struct stu { int age ; };
void fun(int a) { std::cout << "fun函数"<
}
6.名字空间的使用
全部引入: using namespace 名称;
部分引入: using 名称::成员
域 限 定 : 名称::成员
//全部引入:说明接下来的变量如果找不到就是在huaqing的作用域中的。
using namespace huaqing;
//部分引入:只是用stu中的y
using stu::y;
int main(){
x = 123;
fun(y);
stu::area(1,2);
struct huaqing::stu danny = {123};
cout << "age = " <
7.名字空间嵌套
格式: namespace 名字空间1
{
namespace 名字空间2{ 代码};
}
使用:
第一种: using namespace 名字空间1;
名字空间2::变量 = 123;
变量 = 123;
第二种:using namespace 名字空间1:: 名字空间2
变量 = 234; //属于名字空间2中的
名字空间1:: 变量
第三种:名字空间1::名字空间2::变量 = 123;
8.名字空间别名
格式:namespace 别名 = 名字空间名
例如: namespace abc = huaqing::danny
using namespace abc;
代码:
- #include<iostream>
- using namespace std;
-
- //定义名字空间 需要 定义两个变量 int x,y
- //写两个函数 .计算点x ,y 和的三角形的面积
- namespace huaqing
- {
- int danny =12;
- const long num=23;
- struct stu
- {
- int age;
-
-
- };
- //定义函数
- void fun(int a)
- {
- std::cout<<"fun函数"<<endl;
- }
-
- enum week//枚举
- {
- mon,
- tue
- };
- namespace hh
- {
- void ll()
- {
- cout<<"dasdasd"<<endl;
- }
-
- }
- };
-
- namespace gw
- {
- int ss(int x,int y)
- {
- int c=x*y/2;
- return c;
-
- }
-
- };
-
-
- using namespace gw;//说明数据找不到,就到gw 里面去找
- int main()
- {
- int gg=ss(2,2);
- cout<<gg<<endl;
- huaqing::hh::ll();
- return 0;
- }
5.内联函数
1.作用: 在c语言中,函数调用开销。使用频繁的函数开销更大,c++提供了内联函数,直接把函数内容进行复制到调用位置。
一般情况下内联是和类一起使用。
2.关键字:inline 在函数前加一个inline
3.注意事项:内联函数中代码原则上不允许超过10行。(一般5行内代码)
内联函数不允许使用循环语句和switch语句
如果函数不满足以上要求,则编译器会忽略inline关键字。
四、函数重载
1.定义:在相同的作用域下,函数名相同参数列表不同。(有两个相同函数名的函数--不会冲突),重载必须是两个及以上的函数才构成。
2.参数列表不一样:
个数不一样;
类型不一样;
顺序不一样
3.目的
减少对用户调用的复杂性,调用一个函数实现不同的效果(前人种树后人乘凉)
减少函数名的数量,避免名字空间的污染,有利于程序可读性。
注意: 返回值类型不一样不构成重载。
如果参数列表相同会构成函数的重定义错误。
const函数和非const函数构成承载(后续讲)
4.实现原理
g++编译器在编译的时候会把相同的函数名进行内部改名。对用户不可见。
改名规则: 在原本函数名前加_z3表示返回值
参数中如果是string ---->Ss
int-------->i
long -------> l
double------->d
char----------->c
float---------->f
如果有函数int fun(int a,long b,double c)编译后的函数名_z3funild
映射后的函数名 = 返回值+函数名+类型名首字母
5.匹配方式
1.精准匹配:参数列表完全匹配,不需要做任何转换。
2.提升匹配:整形提升(short-->int ,bool-->int, char--->int)
浮点型(float--->double)
3.标准转换匹配:
int--->double, double--->int
long-->double ,double--->long
int-->unsigned int;
4.省略匹配 (...) 比如printf函数。
后续会讲到操作符重载(超级重要)
代码:
- #include<bits/stdc++.h>
- using namespace std;
-
-
- //内联函数
- //作用:在c 语言 函数调用开销,使用频繁的函数开销更大, c++
- //提供了内联函数,直接把函数内容进行复制调用位置
- //一般情况下是和类一起使用
- //
- //关键字:inline 函数前面加入关键字
- //注意事项:内联函数中代码,原则上不允许超过5行(不允许使用循环语句)
- //如果函数不满足以上要求,则编译器会忽略 inline 关键字
- //
- inline int add1(int a,int b)//内联函数减少调用时间
- {
- return a+b;
- }
-
-
-
-
- //函数重载
- //定义:在相同的作用域:
- int add(int a,int b)
- {
- cout<<"int "<<endl;
- return a+b;
- }
-
- int add(int a,int b,int c)
- {
- cout<<"int "<<endl;add
- return a+b+c;
- }
-
- int add(int a,int b,int c,int d)
- {
- cout<<"int "<<endl;
- return a+b+c+d;
- }
-
-
- double add(double a,double b)
- {
- cout<<"double"<<endl;
- return a+b;
- }
-
-
-
- int main(int argc,char* argv[])
- {
- //cout<<add(1,2)<<endl;
- //cout<<add(1.1,2.2)<<endl;
-
- if(argc==3)
- {
- int a=atoi(argv[1]);
- int b=atoi(argv[2]);
- cout<<add(a,b)<<endl;
- }
- if(argc==4)
- {
- int a=atoi(argv[1]);
- int b=atoi(argv[2]);
- int c=atoi(argv[3]);
- cout<<add(a,b,c)<<endl;
- }
- if(argc==5)
- {
- int a=atoi(argv[1]);
- int b=atoi(argv[2]);
- int c=atoi(argv[3]);
- int d=atoi(argv[4]);
- cout<<add(a,b,c,d)<<endl;
- }
-
-
- return 0;
- }
6.缺省参数
1.定义: 缺省参数也叫默认参数,当调用函数不传入参数时,会自动填充参数
2.格式:返回值 函数名(类型 变量= 值,类型 变量 = 值){}
3.注意: 缺省可以做到部分缺省和全部缺省;
函数定义时缺省一定是从右往左缺省,不可以第一个参数缺省,第二个不缺省
只有自定义函数才能缺省,库函数没法缺省
传实参是从左向右缺省,但形参是从右向左缺省。
如果传入了实参,则形参的值就是实参的拷贝,如果没有传入参数,才会使用缺省参数。
实参个数必须大于或者等于无默认值的形参个数。不可以多于所有形参个数。
当使用缺省参数时,需要考虑函数重载的二义性。编译器不知道调用哪一个函数。
4.练习
int add(int a,int b= 0,int c= 0,int d = 0){ return a + b + c + d;}
5. extern "C" ”
使用: 在函数返回值前 加extern "c" 表示按照c语言的规则编译
格式:extern "C" void fun(int a);
extern "C" void fun(int a,int b);
注意: 加上后c语言规则中没有函数重载,不会修改函数名。
注意 "C" 为大写字母
加上extern “c”后,c++的函数和语法都正常只用,只是不修改函数名。
第二种定义方式: extern "c" {int fun(int x); int add(int x,int y);}
c++会默认定义 #define __cplusplus ,用来判断是c文件还是c++文件
案例:
extern "C" int add(int a, int b,int c){
cout << "a = " << a <
}
代码:
- #include<bits/stdc++.h>
- using namespace std;
-
-
- int add(int a=0,int b=0,int c=0,int d=0)
- {
- return a+b+c+d;
- }
-
- int main(int argc,char * argv[])
- {
- //cout<<add()<<endl;
- //cout<<add(1)<<endl;
- //cout<<add(1,1)<<endl;
- if(argc ==2)
- {
- int a=atoi(argv[1]);
- cout<<add(a)<<endl;
- }
- if(argc ==3)
- {
- int a=atoi(argv[1]);
- int b=atoi(argv[2]);
- cout<<add(a,b)<<endl;
- }
- if(argc ==4)
- {
- int a=atoi(argv[1]);
- int b=atoi(argv[2]);
- int c=atoi(argv[3]);
- cout<<add(a,b,c)<<endl;
- }
- if(argc ==5)
- {
- int a=atoi(argv[1]);
- int b=atoi(argv[2]);
- int c=atoi(argv[3]);
- int d=atoi(argv[4]);
- cout<<add(a,b,c,d)<<endl;
- }
-
- }
7、引用 (面试题:引用和指针的区别)
1.引用作用
引用时取别名,可以给变量取别名,避免使用临时变量出现。
2.定义
引用:数据类型 & 别名 = 原名;
指针定义: 数据类型 * 指针= &变量;
注意:引用自己没有内存空间。
如果说原名修改,引用的值也修改了。
引用不允许修改,只可以引用一次。
函数传参的方式:值传递,指针传递,引用传递。
案例:在函数中,使用引用,修改两个变量的值,形参实参都修改。
3.函数参数可以设置成引用
void fun(int& xx,int& yy)
3.函数的返回值为引用
int& fun(int xx);
注意:不可以返回局部变量的引用。
4.引用和指针的区别
第一个:引用的底层实现是指针(自学)
第二个:指针可以修改指向,而引用不可以修改
第三个:引用必须在初始化时进行赋值,而指针可以在使用时赋值
第四个: 没有空引用,引用必须连接到一块合法的内存空间
第五个:有指针的引用,没有引用的指针。int& *p = x是错误的。
第六个:引用的原名释放后操作引用就会错误,指针指向的内存空间释放,操作指针也会错误。
5.常引用
定义常量: const int x = 110;
定义常引用: conset int& x = y; x++;
常引用表示不可以通过引用修改值,但可以通过原名修改值。
常引用一般用于 函数的参数
代码:
- #include<iostream>
- using namespace std;
-
- void ddd(int & a,int & b)
- {
- a=1;
- b=1;
-
- }
-
-
-
- int main()
- {
- int a=2;
- int b=2;
- ddd(a,b);
- cout<<"a="<<a<<endl<<"b="<<b<<endl;
- }
8.new操作符(面试题:请讲new和malloc的区别)
1.new操作符的作用
c++利用new操作来开辟堆空间,和malloc相似。 也需要释放delete
2.匹配
new----delete
malloc---free
3.语法规则
格式1: 类型 * 指针变量 = new 类型标志符;
格式2: 类型 * 指针变量 = new 类型标志符(初始值);
格式3: 类型 * 指针变量 = new 类型标志符[内存单元个数];
代码:
- #include<iostream>
- using namespace std;
- int main()
- {
- //用new创建普通变量
- int* p = new int(10);
- //用new创建一维数组
- int* arr = new int[10];
- //用new创建二维数组
- int(*p1)[10] = new int[2][10];
-
-
- //释放空间
- delete p;
- delete arr;
- delete p1;
- return 0;
- }