第一课C++和C语言的区别

一、面向过程与面向对象

C语言是面向过程的语言,更注重程序的逻辑性,就是将一个程序分解成一个个小模块完成,然后将所有模块有序调动起来,所以它可以更快更直接的形成一个完整的程序。

但是对于大型程序而言,C语言并不利于程序的复用性、扩展性和可维护性

C++是面向对象的语言,更方便于复用和扩展,更注重程序的整体

优缺点总结:

面向过程的优点:因为更快更直接的完成某一种功能,所以性能更好,效率更高,比如单片机、嵌入式、linux等,比较追求性能因素的方向

面向过程的缺点:不方便维护、复用、扩展

面向对象优点:方便于维护、复用和扩展

面向对象缺点:调用时需要实例化,比较消耗资源,导致性能低

C++兼容包含了C语言,同时还增加了函数重载、类、继承、多态、STL库,并且支持泛型编程(模板函数、模板类)

一些常用的概念

封装:就是将零散的东西放到一个集合里

复用:针对某一“”功能去开发,而不是针对某一“”功能去开发

扩展:增加新功能,而不影响原来的功能

//C++支持函数重载
int add(int a,int b)
{
   return a+b;
}

double add(double a,double b)
{
   return a+b;
}

int main()
{
   add(10,20);
   add(10.1,10.2)
}

//C++支持函数模板
template<tempname T>
T add(T a,T b)
{
   return a+b;
}

int main()
{
   add(10,20);
   add('a','b');
}

二、输入和输出

#include<iostream>//C++中标准的输入输出文件
using namespace std;//打开标准命名空间

int main()
{
   int a=10;
   char b='b';
   
   printf("%d  %c\n",a,b);
   
   cout<<a<<"  "<<b<<endl;
   //cout 是ostream的变量
   //<<:输出操作符,是符号被重载的函数
   //endl:换行,本质也是一种函数
   scanf("%d  %c",&a,&b);
   
   cin>>a>>b;
   //cin 是istream的变量
   //>>:输入操作符,是符号被重载的函数
}

三、命名空间

//namespace:命名空间,区分同一作用域下相同的变量名
//命名空间有两种使用方法:1.显示的指定命名空间 命名空间::变量名 2.打开命名空间 using namespace AA 注意:打开多个命名空间可能会产生冲突
namespace AA
{
   int a;
}

namespace BB
{
   int a;
}

//int a;
int main()
{
   int a=10;
   cout<< a <<endl;//局部优先级变量高于全局变量


//:: 作用域运行符,符号前放作用域名,符号后放变量名,符号前没有作用域名默认为全局变量
   //cout<<::a<<endl;

   cout<<AA::a<<endl;
   cout<<BB::A<<endl;
}

四、动态申请空间

//在C中动态申请空间,堆区申请
int *p1=(int*)malloc(sizeof(int));

*p1=10;//赋值
cout<<*p1<<endl;

free(p1);
p1=NULL

//在C++中动态申请空间,在堆区申请
//new是关键字,后面放申请的类型,返回的是对应类型的地址
int *p2=new int;

*p2=20;
cout<<*p2<<endl;

delete p2;
p2=NULL;


int *p3=new int(30);

*p3=30;
cout<<*p3<<endl;

delete p3;
p2=NULL;


int *p4=new int[5];

for(int i=0;i<5;i++)
{
  cin>>*p4[i];
}

for(int i=0;i<5;i++)
{
  cout<<*p4[i]<<endl;
}

delete[]p4;
p4=NULL;


int *p5=new int[5]();//申请空间且初始化为类型的初始值
for(int i=0;i<5;i++)
{
  cout<<*p5[i]<<endl;
}

delete[]p5;
p5=NULL;


int *p6=new int[5]{1,2,3,4,5};
for(int i=0;i<5;i++)
{
  cout<<*p6[i]<<endl;
}

delete[]p6;
p6=NULL;


malloc 和new 的区别:

1.malloc需要提供申请空间的大小,new只需要提供申请空间的类型,会根据申请的类型自动计算大小;

malloc的返回值是是泛型指针void*需要强转,new返回值是所申请的类型

2. malloc是函数,需要依赖头文件,new是关键字,依赖于编译器

3.malloc申请后不能直接初始化,new可以。

4.最重要的:申请结构体和类对象可以直接调用构造函数,delete调用自动调用析构函数

//new一个整型指针
int **p1=new int*;
delete p1;
p1=NULL;


//new一个指针数组
int **p2=new int*[3]
delete []p2;
p2=NULL;


//new一个数组指针
int (**p3)=new (int (*) [3])
delete p3;
p3=NULL;


//new一个二维整型数组
int (*p4)[3]=new int[2][3];
delete p4;
p4=NULL;

五、bool和BOOL

bool,true,false是C++中的关键字,定义变量所需空间大小为1个字节

BOOL是int的别名(typedef),TRUE和FALSE分别是1和0的宏,定义变量所需空间大小为4 个字节

六、字符串

在C语言中使用字符串方法
char *p=(char*)"12345";

p=(char*)"54321"; //修改的不是原字符串的内容而是指针指向的地址

//正确的修改
char arr[5]="1234";

strcpy_s(arr,5,"4321");


//比较两个字符串时
char arr2[5]="4321";

if(arr==arr2) //输出结果为不相等,因为比较的是两个数组的地址
{
   cout<<"相等"<<endl;
}
else
{
   cout<<"不相等"<<endl
}

由上述两个例子可以看出来,在修改字符串的值的时候,不能直接用=,因为修改的不是内存空间里的值,而是指针指向的空间,需要使用函数strcpy_s();比较的时候不能使用==,因为比较的是地址而不是空间里的值,C语言中使用字符串还是不是很方便

#include<string>
using namespace std;

int main()
{
    string str="1234';
    str[1]='9';//通过下标修改
    str="4321";//直接赋值

    string str2="1234";
    if(str!=str2)//通过!=和==直接对比两个字符串
    {
        cout<<"不相等"<<endl;

    }

    //可以像数组一样用for循环去遍历
    for(int i=0;i<str.size();i++) //size()是C++提供的计算字符串大小的方法
    {
        cout<<str[i]<<" ";
    }
    cout<<endl;
    cout<<str.length()<<endl;

    

}

//string的拼接可以直接使用+ +=

string str1="123";
string str2=str1+"456";

str1+="456";

//string的截取 substr(开始截取的下标,截取的长度)
string str3=str1.substr(2,4);

string str4=str1.substr(2,40);//截取长度超过数组长度,默认截取到末尾

string str5=str1.substr(20,4);//截取下标超过数组长度,不合法,相当于数组越界

void fun(const char* c);


string str="abc";
fun(str);//报错

//c_str()可将string转为c_str

fun(str.c_str);

七、增强for循环

//for(相同类型的变量(用于接应元素):操作的数组)
int arr[5]={1,2,3,4,5};
for(int a:arr)
{
    cout<<a<<" ";
}//缺点无法得知相应下标

int *p=new int arr2[3]{1,2,3};
for(int a:arr2)
{
    cout<<a<<" ";
}//非法操作,只知道地址,无法知道数组长度,遍历到哪


string str("12345");
for(char a:str)
{
     cout<<a<<"  ";
}

增强for循环的遍历可以用于数组、string和支持begin、end的容器 

八、C++函数重载

函数重载:对于多个函数,在同一作用域下,函数名相同,参数个数、类型、顺序不同,对返回值没有要求

函数重载方便对一类函数进行命名,减少程序员在命名上花的心思,编译器可以自动匹配

int add(int a,int b);
double add(double a,double b);
int add(int a,int b,int c);

但是要注意,以下两个函数属于函数重定义而不是函数重载

void fun(char *p);
void fun(char p[]);

在C++中,还允许函数的参数指定默认值,规则是,从右往左依次指定而不允许间断。

void fun1(int a,int b,int c=30);

void fun2(int a,int b=20,int c=30);

void fun3(int a=10,int b=20,int c=30)

//错误示范
void fun4(int a,int b=20,int c)

注意:如果函数的声明和定义分开写,一般将默认值写在函数的声明

九、nullptr和NULL

都是为了防止野指针的存在

//NULL是#define NULL 0

void fun(int a);
void fun(int *P);

void(NULL);
//匹配第一个函数

NULL在使用时会出现与整型混用的情况

//正确使用需要强转
fun((int*)NULL)

nullptr是C++提供的关键字,有特定的含义:空指针

fun(nullptr);//可以正确匹配指针参数

//特殊情况仍需强转:当两不同类型的指针作为参数函数重载时
void fun(int *p);
void fun(char *p);


fun((int*)nullptr);

十、引用

1.引用就是对已有的变量(已经存在的空间)起一个别名

2.引用不会再额外申请空间

3.引用一旦声明就必须初始化

4.引用一旦初始化就不可修改

int a=10;
int &b=a;//必须初始化

int c=20;

b=c//不是修改,而是赋值


对于值传递、地址传递、引用传递:

对于修改实参的情况可以使用地址传递和引用传递

空间:

值传递要将实参空间拷贝一份,空间大小不可控

地址传递开辟一个指针大小的空间,由指针类型决定,大小

引用传递不开辟空间

值传递对于复合类型,类、结构体可能出现浅拷贝问题

注意:引用可以const,但是会出现警告

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值