c++
前言
c和c+的关系
c++是对c的升级和完善
c的缺陷
1、不严谨
char *p=“hello”;*p=‘*p’;
const int i;
2、名字冲突 作用域
3、面向过程
4、无法解决大规模问题
c与c++
1、linux–ubuntu上的c++编译
编译c++程序流程
预处理:(处理所有 # 开头的东西,例如:头文件展开 宏替换 条件编译等)
g++ -E *.cpp ---> *.i
编译:
g++ -S *.i ---> *.s
汇编:
g++ -c *.s ---> *.o
链接:
g++ *.o ---> a.out
2、输入和输出
主要用于代码的调试
cout : 输出流对象, 自动匹配类型
cin : 输入流对象,空格或者回车都可以区分
eg:
#include <iostream>
using namespace std;
int main()
{
int a;
char ch;
float b;
double d;
char buf[100];
string str;
cout << "please input: ";
#if 0
cin >> a;
cin >> ch;
cin >> b;
cin >> d;
cin >> buf;
cin >> str;
#endif
cin >> a >> ch >> b >> d >> buf >> str;
cout << a << " " << ch << " " << b << " " << d << " " << buf << " " << str << endl;
return 0;
}
3、引用类型
(1).C语言中是怎么给数据类型取别名的 typedef
#include <stdio.h>
typedef int data_t;
typedef int (*ptrArray)[int];
int main()
{
int (*p)[int];
ptrArray p;
return 0;
}
(2).C++新增,给变量取别名(reference)
int &b=a;
b与a的地址与值都一样
注意:两个变量不能取同一个别名
(3).引用传参
通过取别名来实现地址改变
fun(a,b);
void fun(int &x,int &y);//x== a,y== b,连地址都是一样的
更高效,因为没有开辟新的空间,因为变量的地址是一样的
int *p;
cout<<*p<<endl;
因为指针存在野指针,不安全,闯红灯行为,可能出事可能不出事,和指针相比,引用更安全。
4、内联函数
普通调用函数:
void fun(void)......
int n=0;
while(n<5)
{
fun();
n++;
}
缺陷:跳转10次
c++提供了一种提高效率的方法:内联函数
语法:inline 存储类型 数据类型 函数名(参数列表);(以空间换时间)
inline void fun(void)......
while(n<5)
{
fun();
n++;
}
//替换为 --->
//cout<< "call fun " << endl;
//cout<< "call fun " << endl;
//cout<< "call fun " << endl;
//cout<< "call fun " << endl;
//cout<< "call fun " << endl;
注意:内联函数的限制:
使用内联函数可以节省运行时间,但却增加了目标程序的长度。(以空间换时间)
因此一般只将规模很小(一般为5个语句以下)而使用频繁的函数声明为内联函数。
由于多个源文件是分开编译的,要内联就应该把内联函数声明在头文件中。
内置函数中不能包括复杂的控制语句,如循环语句和switch语句.
5、函数重载
大规模代码,函数重名不可避免
(1)函数重载:
在同一个作用域下,函数名相同,参数不同(个数不同,类型不同,个数和类型都不同),返回值可相同可不相同。
#include <iostream>
using namespace std;
int add(int x)
{
return x+x;
}
int add(int x,int y)
{
return x+y;
}
float add(float x,float y)
{
return x+y;
}
double add(double x,double y)
{
return x+y;
}
int main()
{
cout << add(5) << endl;
cout << add(5,10) << endl;
return 0;
}
小数是double类型,要调用float类型需要处理
add(1.2f,2.4f);//说明数据是float类型
写一个double类型的函数
float a=1.2,b=2.4; add(a,b);//调用float类型的函数
(2)默认参数:
1.默认参数,函数调用时可以不用传参
2.如果给某一参数设置了默认值,那么在参数表中,其后所有参数也必须设置默认值
3.如果进行了函数声明,只能在声明中设置默认值
#include <iostream>
using namespace std;
//只用给第一个赋值
int add(int x,int y=20,int z=30)
{
return x+y+z;
}
int main()
{
cout << add(1) << endl;
return 0;
}
多个重载函数都有默认参数时,出错
编译器不会帮你选择,优先选择同类型的函数,没有时可以隐式转换的也可以用,int,double互相都可以转换。
6、作用域和名字空间
作用域
局部域:局部变量所在作用域
全局域:全局变量所在的作用域
名字空间域:管理函数 变量 类等;(大规模代码,之前已经用函数重载解决一部份问题,但是碰到函数名一样,参数也一样的情况,用名字空间域来解决重名)
用法:
namespace 名称
{
函数
变量
类
}
:: --->作用域访问符
::m --->访问全局变量m
类域,每个类空间都定义了自己的域
#include <iostream>
using namespace std;
namespace A
{
void fun()
{
cout << "call fun1" << endl;
}
}
namespace B
{
void fun()
{
cout << "call fun2" << endl;
}
}
int main()
{
A::fun();
B::fun();
using namespace A;//申明之后所有的fun都是名字空间域A的
fun();
B::fun();//依旧可以
}
7、new和delete
c:–>malloc和free
c++:–>new和delete
#include <iostream>
using namespace std;
#include <cstdio>
#include <string.h>
#include <malloc.h>
int main()
{
#if 1
char *p=(char *)malloc(1024);
strcpy(p,"hello world");
printf("%s\n",p);
free(p);
#endif
#if 0
char *p=new char [1024];
strcpy(p,"hello");
cout<<p<<endl;
delete [] p;
#endif
//int *q=new int[1];
int *q=new int;
*q=100;
cout<<*q<<endl;
delete q;
//delete [] q;
return 0;
}
8、严格的数据类型
c++有更严格的数据类型检查:
1.不能将char * 给int *
2.不能用char * 指向const char *
3.函数返回值的类型,要一致
4.c++中的const是真的该碧聊,记得一定要赋初值(c语言中可以通过指针修改const修饰的局部变量)
5.强制类型转换
int i;
char ch;
ch=(char)i;//都对
ch=char (i);
9、练习实用
【学生成绩管理系统】
输入学生信息(姓名,学号,成绩),可以根据学生学号输出学生信息,也可以根据学生成绩输出学生信息。
#include <iostream>
#include <string.h>
using namespace std;
typedef struct stu{
char buf[20];
int id;
float score;
}Stu;
Stu arr[20]={{"小明",1,100},{"小刚",2,99},{"小红",3,88}};
void stu_get(int id_new,int top)
{
int i=0;
for(i=0;i<top;i++)
{
if(arr[i].id==id_new)
cout<<arr[i].buf<<" "<<arr[i].id<<" "<<arr[i].score<<endl;
}
}
void stu_get(float score_new,int top)
{
int i=0;
for(i=0;i<top;i++)
{
if(arr[i].score==score_new)
cout<<arr[i].buf<<" "<<arr[i].id<<" "<<arr[i].score<<endl;
}
}
int main()
{
while(1)
{
cout<<"请输入选项:"<<endl;
cout<<"1: 根据学生学号输出学生信息"<<endl;
cout<<"2: 根据学生成绩输出学生信息"<<endl;
cout<<"3:输入学生信息"<<endl;
cout<<"4:退出"<<endl;
int a,id_get;
float score_get;
int n,i=0;
int top=3;
cin>>a;
switch(a)
{
case 1:cout<<"请输入学生学号:"<<endl;
cin>>id_get;
stu_get(id_get,top);break;
case 2:cout<<"请输入学生成绩:"<<endl;
cin>>score_get;
stu_get(score_get,top);break;
case 3:cout<<"要输入几个学生信息:"<<endl;
cin>>n;
cout<<"请输入学生信息:"<<endl;
while(n--)
{
cin>>arr[3+i].buf>>arr[3+i].id>>arr[3+i].score;
i++;
top++;
}break;
case 4: return 0;
default:cout<<"请输入正确的选项!"<<endl;break;
}
}
return 0;
}
代码运行: