- 🌸博主主页:@釉色清风
- 🌸文章专栏:C++
- 🌸今日语录:自律以修身,自省以观己。自学以长识,自处以蓄力。
🌻Hi~大家好,这次文章是C++的初步认识,包括从C语言到C++、C++的数据类型和运算符、C++的输入输出、内置函数、有默认参数的函数、函数重载、函数模板等等。适用于刚刚入门C++的小伙伴,可以帮助大家在短时间内了解到C++的一些特性。希望对大家有帮助。
C++的初步认识
- 🌼由C语言到C++
- 🌻C++对C的增强
- 🌼C++的数据类型和运算符
- 🌻C++的数据类型
- 🌻布尔型数据(bool)及其运算
- 🌻结构体类型定义变量struct可以省略
- 🌻强制类型转换
- 🌻C++新增运算符
- 🌻新增动态内存分配的运算符
- 🌻新增作用域运算符
- 🌻变量的引用
- 🌻常变量
- 🌼C++的输入和输出
- 🌻输入流和输出流的基本操作
- 🌻cin和>>
- 🌻cout和<<
- 🌻输出格式可以由程序员控制吗?
- 🌻输入输出的格式控制符
- 🌼内置函数
- 🌻内置函数(inline function)概念
- 🌼有默认参数的函数
- 🌻默认值的参数在最右端
- 🌼函数重载
- 🌼函数模板
- 🌻 定义函数模板
- 🌼字符串类
- 🌻字符串数组
🌼由C语言到C++
C语言,是于1972年在贝尔实验室D.M.Ritchie和K.Thompson为计算机专业人员设计的语言,大多数系统软件和许多应用软件都是用C语言编写的,但是随着软件规模的增大,用C语言编写程序渐渐显得有些吃力了。
于是在20世纪80年代初,在贝尔实验室Bjarne Stroustrup博士及其同事在C语言的基础上成功开发C++。C++与C语言兼容,保留了C语言原有的优点,增加了面向对象的机制。
🌻C++对C的增强
所以,可以理解为 C++是对C语言的增强。
在原来面向过程的机制基础上,对C语言的功能做了不少扩充。
- 用C语言编写的程序基本上可以不加修改地用于C++。
- 增加了命名空间、引用、域作用符等大型程序开发需要的机制。
- C++既可以用于面向过程的结构化程序设计,又可以用于面向对象的程序设计,是一种功能强大的混合型的程序设计语言。
增加了面向对象的机制。
- 面向对象程序设计,是针对开发较大规模的程序而提出来的,目的是提高软件开发的效率。
- 面向对象和面向过程并不矛盾,而是各有用途、互为补充。
- 最新的标准,支持范型编程。
C++是C语言的超集,C语言是C++的子集。
🌼C++的数据类型和运算符
第一个C++程序
#include <iostream>//包含头文件iostream
using namespace std;
int main()
{
cout<<"Hello World";//输出
return 0;
}
其中头文件iostream包括输出流和输入流。
C++头文件和C语言头文件的一些区别:
🌻C++的数据类型
C++的数据类型在C语言的数据类型上有所扩充。
如上图所示。
🌻布尔型数据(bool)及其运算
- C和C++中都用数值1代表"真",用0代表"假"。
- C++增加了逻辑型数据类型:bool型
- 逻辑型常量只有两个,即false(假)和true(真)。
- 逻辑型使程序更直观易懂。
- 在编译系统处理逻辑型数据时,将false处理为0,将true处理为1.
- 在实际中,非0被视为"真",0被视为“假”。
- 逻辑型数据可以和数值型数据进行算术运算。
- 逻辑运算的规则照旧。(真值表)
- bool类型占1个字节。
bool flag=ture;
bool found=false;
示例:
#include <iostream>
using namespace std;
int main()
{
//创建bool数据类型
bool flag = true;
cout << flag << endl;
//重新赋值
flag = false;
cout << false << endl;
//故本质上1代表真,0代表假
//bool类型所占类型空间
cout << "bool类型所占的内存空间" << sizeof(bool) << endl;
return 0;
}
运行结果如下:
🌻结构体类型定义变量struct可以省略
结构体类型在定义变量时,其前struct可以省略。
示例:
#include <iostream>
using namespace std;
struct student
{
int no;
float math;
};
int main()
{
int n;
cin >> n;
student wang;//C语言中,必须是struct student wang
wang.no = n;
cin >> wang.math;
cout << wang.no << " " << wang.math << endl;
return 0;
}
🌻强制类型转换
支持两种格式:
- (数据类型)(表达式)——c语言风格
- 数据类型(表达式)——c++风格
示例:
double x=2.5,y=4.7;
int a=25,b;
b=a+(int)(x+y);
y=double(5%3);
🌻C++新增运算符
🌻新增动态内存分配的运算符
在C语言中,由malloc()函数分配内存,由free()函数释放内存。
在C++中,分配内存时用new运算符,释放内存用delete运算符。
分配内存用new运算符
格式如下:
- 指针变量=new 数据类型
- 指针变量=new数据类型[数组大小];
示例:
int *p1,*p2,*p3;
p1=new int;
p2=new int[5];
p3=new int(5);//分配一个int型变量空间,并赋值为5.
new为程序分配一块内存空间,并返回指向该内存的首地址。
释放空间用delete运算符
格式如下:
- delete指针变量
示例:
delete p1;
delete p3;
delete []p2;//释放p2所指向的数组空间
用new获取的内存空间,必须用delete进行释放。
🌻新增作用域运算符
#include <iostream>
using namespace std;
float a=2.4;//全局变量a
int main()
{
int a=8;//局部变量a
cout<<a<<endl;//a为局部变量
cout<<::a<<endl;//::a表示全局变量a
}
我们再来看一个相似的示例:
#include <iostream>
//这儿不写使用的命名空间
float a=2.4;
int main()
{
int a=8;
std::cout<<a<<std::endl;
std::cout<<::a<<std::endl;
}
std::,表示使用命名空间std空间中定义的标识符。
🌻变量的引用
C++对C的一个重要扩充:对一个数据可以使用“引用”
引用的作用为:为一个变量起一个别名,例如
示例:
int a;//定义a是整型变量
int &b=a;//声明b是a的引用,b是a的别名
a=20;
cout<<b<<endl;
声明变量b作为引用类型,不另开辟内存单元来存放b的值。
- b和a占内存中的同一个存储单元,它们具有同一地址。
- a或b的作用相同,都代表同一变量。
- 引用可以理解为:使变量b具有变量a的地址。
&是引用声明符,并不代表地址,不同于"把a的值赋给b的地址"。
引用的简单使用:
#include <iostream>
#include <iomanip>
int main()
{
int a=10;
int &b=a;//声明引用类型变量要同时初始化
a=a*a;
cout<<a<<" "<<b<<endl;
cout<<b<<" "<<a<<endl;
return 0;
}
增加引用类型,主要用于扩充传递数据功能。
#include <iostream>
using namespace std;
void swap(int &a,int &b);
int main()
{
int i,j;
i=3,j=5;
swap(i,j);
cout<<"i="<<i<<" "<<"j="<<j<<endl;
return 0;
}
void swap(int &a,int &b)
{
int temp;
temp=a;
a=b;
b=temp;
}
🌻常变量
常变量:在定义变量时,加上关键字const,则变量的值在程序运行期间不能改变。
例如:
const int a=3;
const int b=#+6,c=3*cos(1.5);
在定义变量时必须同时对它初始化,此后它的值不能再改变。
示例:
#include <iostream>
using namespace std;
const int price =30;
int main()
{
int num,total;
num=10;
total=num*price;
cout<<"total="<<total<<endl;
return 0;
}
符号常量(宏定义)vs常变量
🌼C++的输入和输出
C++的输入和输出都用"流"(stream)的方式实现。
注意:
流对象cin、cout和流运算符的定义存放在C++的输入输出库iostream中;cout、cin并不是C++本身提供的语句,运算符<<和>>也不是C++本身提供的运算符,要在程序中使用cin、cout和流运算符,必须先#include。
🌻输入流和输出流的基本操作
格式:
- cout<<表达式1<<表达式2<<…表达式n;
- cin>>变量1>>变量2>>…>>变量n;
示例:
cin>>a>>b>>c;
cout<<"a="<<a<<"\tb="<<"\tc="<<c<<endl;
<<和提取运算符>>的优先级与结合性?
int a=1,b=4,c=8;
//逗号运算符的优先级最低
cout<<a,b,c; //输出1
cout<<a,b,c<<endl;//报错;
cout<<a+b+c<<endl;//输出13
🌻cin和>>
输入中,有多种方式对数据进行分隔
int a,b,c,d;
cin>>a>>b>>c>>d;
下面是各种可选的输入形式
程序将自动识别符号:
#include <iostream>
using namespace std;
int main()
{
int a,b;
char op;
cin>>a>>op>>b;
cout<<"result"<<"\n";
cout<<"a:"<<a<<"\n";
cout<<"b:"<<b<<"\n";
cout<<"op:"<<op<<"\n";
return 0;
}
- cin不会读入空格,回车,将其当成分隔符。
- 将“分隔符”读入,找getchar()函数。
🌻cout和<<
在用cout输出时,系统会自动判断输出数据的类型,使输出的数据按相应的类型输出。
在必要时,一条语句中多个数据输出合理分隔。
示例:
int a=4;
float b=345.7888435;
char c="a";
cout<<a<<"\t"<<b<<" "<<c<<endl;//输出浮点型数据默认输出6位数
输出格式如下:
🌻输出格式可以由程序员控制吗?
目标:输入数时满足一些特殊的要求
- 规定字段宽度
- 保留的小数位数
- 数据向左或向右对齐等
方法:使用输入输出流中的控制符
- 设置数值的技术(8,10,16)
- 设置填充
- 设置精度
- 设置对齐
- 设置其他方式
示例:
#include <iostream>
#include<iomanip> //不要忘了包含此头文件
using namespace std;
int main()
{
double d=225.0/7.0;
cout<<"d="<<d<<endl;
cout<<setiosflags(ios::fixed);
cout<<"d="<<setprecision(5)<<d<<endl;
cout<<"d="<<setrecision(2)<<d<<endl;
return 0;
}
🌻输入输出的格式控制符
如下面这张表:
🌼内置函数
🌻内置函数(inline function)概念
我们知道,调用函数时需要一定的时间和空间的开销。于是,我们在找一些提升效率的方法,既要用到函数这样的形式,也希望效率提升。在C语言中,提升效率的方法是宏定义。
#define area(a,b) (a)*(b)
在C++中,将功能做的更彻底,不是像宏定义一样换概念,而是定义了内置函数。
内置函数在编译的是否将所调用函数的代码直接嵌入到主调函数中。内置函数,有时也叫内联函数。
示例:
关于内置函数
- 内置函数只是影响编译过程。
- 使用内置函数可以节省运行时间,但却增加了目标程序的长度
- 一般来说,只将规模很小(一般为5个语句以下)而使用频繁的函数(如定时采集数据的函数)声明为内置函数。
- 内置函数中不能包括复杂的控制语句,如循环语句和switch语句。
- 对函数作inline声明,只是程序设计者对编译系统提出的一个建议,而不是指令性的。
🌼有默认参数的函数
在函数声明中我们剋给出函数参数的值:
float area(float r=6.5);
在函数调用时,可以不给出实参,如:
area();//相当于area(6.5)
也可以给出形参:
area(7.5);给出形参,形参r得到7.5
所以:
- 函数声明时形参指定默认值
- 函数调用时,市场的个数可以与形参的个数不同
- 实参未给定时,从实参的默认值得到值。
例如:
函数声明时:
float volume(float h,float r=12.5);
在函数调用时,我们可以给出不给出默认参数的值:
volume (45.6);//相当于volume(45.6,12.5)
也可以给出默认参数的值:
volume(34.2,10.4);
同时,在函数声明时的形参名可以不写:
float area(float=6.5);
float volume(float,float=12.5);
🌻默认值的参数在最右端
实参与形参的结合必须时从左至右顺序进行的
指定默认值的参数必须放在列表中的最右端,否则出错。
例如:
void f1(float a,int b=0,int c,char d='a');//报错
void f2(float ,int c,int b=0,char d='a');//正确使用
如果调用上面的f2函数,可以采用下面的形式:
f2(3.5,5,3,'x');//形参的值全部从实参得到
f2(3.5,5,3);//最后一个形参取默认值'a';
f2(3.5,3);//最后两个形参取默认值,b=0,d='a'
利用带默认参数的函数实现求非负数的最大值
int max(int a.int b,int c=0);//仅声明时默认
int main()
{
int a,b,c;
cin>>a>>b>>c;
cout<<"max(a,b,c)="<<max(a,b,c)<<endl;
cout<<"max(a,b)="<<max(a,b)<<endl;
return 0;
}
int max(int a,int b,int c)//定义时不默认
{
if(b>a) a=b;
if(c>a)a=c;
return a;
}
🌼函数重载
第一种情况是,函数重载即,同名同体,但接口不同。(即重载的函数名相同,参数、函数体相同,仅数据类型不同。)
例如:
#include <iostream>
using namespace std;
//函数声明
int max(int a,int b,intc);
double max(double a,double b,double c);
long max(long a,long b,long c);
int main()
{
int i1,i2,i3,i;
cin>>i1>>i2>>i3;
i=max().i1,i2,i3);
cout<<"i_max="<<i<<endl;
double d1,d2,d3,d;
cin>>d1>>d2>>d3;
d=max(d1,d2,d3);
cout<<"d_max="<<d<<endl;
long g1,g2,g3,g;
cin>>g1>>g2>>g3;
g=max(g1,g2,g3);
cout<<"g_max="<<g<<endl;
return 0;
}
int max(int a,int b,int c)
{
if(b>a) a=b;
if(c>a) a=c;
return a;
}
double max(double a,double b,double c)
{
if(b>a) a=b;
if(c>a) a=c;
return a;
}
long max(long a,long b,long c)
{
if(b>a) a=b;
if(c>a) a=c;
return a;
}
第二种情况是,重载函数,同名不同体,参数个数有区别。
我们总结以下函数重载(function overloading):一名多用
- 函数的重载,用同一函数名定义多个函数,这些函数的参数个数或者参数类型不同。
- 函数的重载使得一个函数名字重新赋予心得含义,使得一个函数名可以多用。
- 在编程时,要实现细节不同的同一类的功能时,用函数的同载,例如:
不能算作重载情况:
int f(int);
long f(int);
void f(int);
函数的参数个数、参数类型或参数顺序三者中必须至少有一个不同,函数返回值可以相同也可以不相同。
同时,在使用重载函数时,同名函数的功能应当相同或相近,不要用同一函数名去实现完全不相干的功能,虽然程序也能运行,但是可读性不好,使人莫名其妙。
函数重载与参数的默认值不要冲突,在编译系统时,调用函数时会产生歧义。
🌼函数模板
在重载函数中,当我们声明重载函数时,函数本身它们的函数体是一样的,分别定义每一个函数,比较冗杂。
所以为了解决这个问题,我们就发展出了函数模板(function template),它用来替代重载函数的多次定义。
下面我们来简要了解以下函数模板
- 所谓的函数模板,实际上是建立一个通用函数,其函数类型和形参类型可以不具体·指定,而是用一个虚拟的类型来代表。
- 凡是函数体相同的函数都可以用这个模拟来代替,不必定义多个函数,只需在模板中定义一次即可。
- 在调用函数时系统会根据实参的类型来取代模板中的虚拟类型,从而实现了不同函数的功能。
下面我们来看一个例子:
#include <iostream>
using namespace std;
template<typename T>
T max(T a, T b, T c)
{
if (b > a)a = b;
if (c > a) a = c;
return a;
}
int main()
{
int i1 = 185, i2 = -76, i3 = 567;
double d1 = 56.87, d2 = 90.23, d3 = 3214.78;
long g1 = 67859, g2 = -482947, g3 = 1984747;
cout << "i_max=" << max(i1, i2, i3) << endl;
cout << "f_max=" << max(d1, d2, d3) << endl;
cout << "g_max=" << max(g1, g2, g3) << endl;
return 0;
}
🌻 定义函数模板
- 先进行模板声明,再定义函数
template <typename T>
template <class T>
- 虚拟类型名即可以被用于函数定义
- 在对程序进行编译时,编译系统会将函数名与模板相匹配,将实参的类型取代了函数模板中的虚拟类型T。
声明模板后,我们对函数进行定义。
T max(T a,T b,T c)
{
if (b>a)a=b;
if(c>a)a=c;
return a;
}
cout<<max(i1,i2,i3);
cout<<max(d1,d2,d3);
cout<<max(g1,g2,g3);
同时,在一个函数中,需要的类型参数可以不止一个,可以根据需要确定个数。如:
template <class T1,typename T2>
函数模板不仅仅是将数据类型参数化,函数模板更是将数据数据类型也参数化了。
🌼字符串类
C语言中的字符串函数包含在头文件string.h中。
C++中的新成分。
在C语言中,
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char srt1[50],str2[50],temp[50];
cout<<"please input strings:";
cin>>str1>>str2;
if(strcmp(str1,str2)>0)
{
strcpy(temp,str1);
strcpy(str1,str2);
strcpy(str2,temp);
}
cout<<"now,they are:";
cout<<str1<<","<<str2<<endl;
}
在C++中
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1,str2,temp;
cout<<"please input strings:";
cin>>str1>>str2;
if (str1>str2)
{
temp=str1;
str1=str2;
str2=temp;
}
cout<<"now,they are:";
cout<<str1<<","<<str2<<endl;
}
使用string类型很任性。
- 为字符串直接赋值
string string1,string2;
string1="Canada";
string2=string1;
对字符串变量中某一字符操作
string word ="Then";
word[2]='a';
- 用加号连接字符串
string string1="C++";
string string2="Language";
string1=string1+string2;
- 用关系运算符直接比较字符串
==、>、<、!=、<=、>=
if (str1>str2)
- 字符串输入输出
cin>>string1;
cout<<string2;
string 类型并非C++亲生,但是,很强大。
string并不是C++语言本身具有的基本类型,它是C++标准库中声明的一个字符串类。
文件包含#include 或#include .
🌻字符串数组
定义一个字符串数组并初始化
string name[5]={"Zhang","Li","Wang","Tan"};