提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
TODO:写完再整理
本文先对C/C++语言语法做个简单的介绍,具体内容后续再更【防盗标记–盒子君hzj】,其他模块可以参考去我其他文章
提示:以下是本篇文章正文内容
1、C语言已经有模块化和结构化的优势,但是还是一个面向过程的语言
2、C++语言增加了面对对象的机制,同时支持面向过程
3、C++对C语言的扩充
(1)C++变量的定义可以在程序中的任意一行(这样在大型程序中,变量灵活定义能大大提高可读性,但是C语言用声明也能解决这个问题)
(2)提供了标准的输入输出对象,cin\cout
(3)**用const代替了define做宏定义**
(4)提供函数重载、函数模板、带默认值的函数
【防盗标记--盒子君hzj】
(5)**引用类型**
(6)单目作用域运算符
(7)string类型字符串
(8)使用了new和delete代替了malloc和free函数
(9)从C语言的面向过程的编程方式,过度到面向对象的的编程方式。这样更有效的管理复杂,庞大的代码
(10)C++能开发,编译器、操作系统、应用软件、游戏等等。
.
1、记事本(notepad++)+命令行(上手慢,大牛级别)
2、visual C++6.0(太古老,和现在流行的系统会有冲突)
3、VS2015(功能强大,安装包和一样强大)
【防盗标记--盒子君hzj】
4、code::block(比较好的C++开发工具,适合专业人员)
5、集成IDE:DEV C++(太老了)、CLion(非常好,收费)、CFree(国产),XCode(适合苹果系统)等等
我当然使用的是廉价的vscode啦~
.
把一个复杂的对象,不断细分成一个子对象,逐一突破,每个对象由属性和行为两个要素
面对对象的思维转变:程序员不在面对一个个函数和变量,而是要放眼大局,**面对一个个对象看待问题**
.
面向过程类似于企业老总什么都要自己亲力亲为,累得要死
面向对象类似于企业老总吧公司分成几个板块,任命经理对象,由经理对象处理好各自板块的问题,我仅仅需要管理好经理即可。
.
1、封装(类似于分公司):把对象的属性和方法结合成一个独立的系统单位,并尽可能的隐藏对象的内部细节(包括复杂的函数实现和变量定义),这样能把程序变得更加“仔细”,更加“模块化”
2、抽象(类似于一个总公司):相当于总公司要对分公司下达的一些指令和指标。如同一个协议吧
3、继承:类似于儿子继承了老爸(基类,父类)的所有属性,并在这个基础上儿子(子类)有所扩展(属性和方法)
4、多态:和继承相关,就是儿子对爸爸有所扩展的部分,同时能继承多个基类
在团队开发中,这些特点更有利于分工合作~
.
1、没有数组溢出大小检查
2、C++面向对象的编程一般程序比较长,因为要对每个对象进项详细的描述,但是这样的好处是主函数特别精简,可读性非常高
.
1、定义一个有属性(变量)和方法(函数)的类(模板)
2、实现方法的过程(构造函数)
【防盗标记--盒子君hzj】
3、调用方法实现对象的功能
.
1、面向过程编程偏向于关注对数据的处理过程,面向对象的编程是偏向于对数据进行怎行的处理,两者有很多相通的地方。
2、面向对象的编程方法的一个重要特征是用一个对象把数据和处理数据的函数封装到一起。越高级的语言封装的越多,每个函数只处理调用它的那个对象,所包含的数据,所有的数据偶属于同一个对象,类仅仅是一个描述对象的模板
3、面向对象是一个国家分成每个家庭进行管理,一出错仅仅某个家庭受害;面向过程是一个国家一起管理,一出错大家一起受伤害
静态成员,静态对象、静态方法、虚方法、抽象方法、多态
.
意思是程序在不进行动作的时候一直等待,一直占用资源部释放
相反的,还有非阻塞编程,**多进程多线程编程**
.
.
布尔型bool不是true就是false
定义变量
1、用数据结构定义变量,如int a\float a \double a\char a
2、用类定义变量,如,类名 a;[app a;]
【防盗标记--盒子君hzj】
**1、功能**:可以把许多同类型的值存储在同一变量名下
数据类型声明:数组仍然要被声明为某一特定的类型:int \float\double\char等等
**2、定义方法**:type name[x]
**3、注意**:不同类型的值不能放在同一数组上
**4、字符串储存类型**:在C语言中,字符串其实是储存在一个字符数组里的;在C++语言中,不必这么做了,C++提供了std::string这个类
getline(std::cin>>str),直接输入一行字符串存储在str中
【防盗标记--盒子君hzj】
**5、实质**:计算机是把数组以一组连续的内存块保存的,如:int array[3]={1,2,3};
这说明数组是拥有很多个地址的,而且每个地址都对应这一个元素,同一数组拥有一样的变量名(都是array)
(1)程序是在内存里面存储的,但是它们是在内存里面运行的,所以地址是特指内存里面的地址
(2)变量的地址在程序的运行过程中是不会被改变的,但是变量在程序不同时间段上运行时会改变的,因为程序运行完成后会释放内存和变量
指针是专用来存放地址的特殊类型的变量
绝大部分的高级或多或少都会使用了指针,但是就是被包装了起来
指针能完成很多其他工具没有完成的任务,如对内存的调用
【防盗标记--盒子君hzj】
对于一个变量,我们有两种方法对它进行寻址
方法一:通过变量名
方法二:通过地址,需要“取址”操作符--“&”,它的作用是获得变量的地址
“&”d的使用方法:
--int var=123;
--std::cout<<"var的地址:"<<&var
--type*pointername;【*代表指针变量】,如
方法一:
--int *p;【定义一个指针变量p】
--int pp=123;【定义一个整形变量pp】
--p=&pp【把整形变量pp的地址赋给指针变量p里】
方法二:
--int pp=123;
--int*p=&pp;【一步到位】
(1)整型数据结构的变量要用整型数据结构的指针指向,做到意义对应,因为内存对齐问题
(2)int *p1 p2 p3【这样定义仅有p1是指针变量,p2 p3都是整形变量,这样写的程序是具有极大迷惑力的,一般不同类型的变量分开写】
【防盗标记--盒子君hzj】
(1)原理:指针变量可以让我们知道变量的地址,这样我们就可以通过指针访问该地址的数据(走后门)
(2)方法:解引用处理:即在指针变量前加上*【可以这么理解加*往上层走,加&往下层走】
方法一:
--int a=100;
--int*aa=&a;
--std::cout<<*aa;【输出的是100】
方法二:
--int a=100;
--std::cout<
(1)--int*aa=&a;【这种形式是指针的定义,定义是带数据结构的】
(2)--*aa=1000;【这种形式是指针的解引用,引用不带数据结构的】
背景:计算机是把数组以一组连续的内存块保存的,如:int array[3]={1,2,3};
这说明数组是拥有很多个地址的,而且每个地址都对应这一个元素,同一数组拥有一样的变量名(都是array)
【防盗标记--盒子君hzj】
实际上,数组的名字就是一个指针(变量的名字也是指针),指向数组的基地址(第一个元素),故下面两句本质是一样的
--int*ptr1=&array[0];
--int*ptr2=&array;
(1)方法:ptr++;
(2)注意:这里的指针++不是地址位置简单的++,而是以数据结构对应的地址数目++,因为不同的数据结构的地址数目是不一样的
(3)一般用法:
--int array[10]={1,2,3,4,5,6,7,8,9,10}; 【定义一个数组】
--int *array=&array 【定义一个指针,指向该数组的首地址】
--std::cout<<*array; 【输出数组的第一个元素】
--*array++;
--std::cout<<*array; 【输出数组的第二个元素】
.........
注意*array+1和*(array+1)的区别:优先级问题
--int a=100;
--int b=1000;
//子函数
void add(int *one,int *two)
{
int sum;
sum=*one+*two;
std::cout<
背景:指针也可以指向结构体,方法和指向其他任何变量一样(类似于数组)
步骤:
第一步:
(1)定义结构体:
struct name
{
type1 varname1;
type2 varname2;
.....
};
第二步:
(2)赋值语法
name hzj={1,2};
【防盗标记--盒子君hzj】
第三步:
(3)创建指向该结构变量的指针
name *pzhj=&hzj;
注意:指针的类型必须和结构体变量的类型是一样的,都是name
结构体变量指针的调用
方法一:返回层次操作:通过"."解引用符
(*pzhj).varname1=100; 【这里改变了hzj这个结构体内的varname1成员的值】
*pzhj本质上和hzj一样,都是结构体变量;pzhj是hzj的的基地址,因为hzj结构体变量的成员数据结构不一样,不可以使用像数组变量"++"的形式
方法二:指针层面操作:通过"->"解引用符
phzj->varname1=100; 【这里是直接操作phzj指针】
使用this指针的原则:如果**代码不存在二义性隐患**,就不必使用this指针
this指针是类的自动生成、自动隐藏的 私有成员,存在于类的非静态成员函数中,指向被调用函数对象的所在地址
this指针是当前指针地址的意思
【防盗标记--盒子君hzj】
数组的数组名和下标操作符[]可以对应为指针的基地址指针和对应的指针运算++
int a[20];
int *x=a;
指针变量x指向a的首地址即a[0]的地址,a[0]和*x都代表数组的第一个元素 ,根据数组和下标操作和指针的指针运算,a[1]等价于*(x+1)......a(20)等价于*(x+20)
1、功能:动态内存可以让函数返回一个地址,以前函数一般都是仅能返回一个标量值(整型浮点型指针等等)
基本思路:
2、使用方法:函数返回一个地址(该函数是指针函数,如,int *funtion(int a);)
在函数里调用new语句为某个对象或者某个基本数据类型分配一块内存,
再把该块内存的地址返回给主程序的代码,主程序的代码使用完这个地址后使用delete对该块内存进行释放
3、注意:任何一个指针函数都不应该把函数内部的指针(局部变量的指针)作为返回值,
因为当函数执行完毕后,局部变量自动被清空,返回的地址是一个乱码。
返回的地址应该是用new动态分配的内存基地址
【防盗标记--盒子君hzj】
结构体structure(本质是面向对象,对象的基础)
C和C++的程序完全可以根据具体情况自定义一些新的数据类型,
并创建新的数据类型变量,这个为对象的创建打下了基础
是一种有程序员定义的,由多种变量类型组合而成的数据类型【组合】
**(1)定义语法:**
struct name
{
type1 varname1;
type2 varname2;
.....
};
**(2)调用赋值语法:**
(1)调用赋值语法方法一:用“.”对结构成员进行赋值及调用
name hzj; //创建一个name结构类型的hzj
hzj.varname1=1; //成员进行赋值
hzj.varname2=2;
【防盗标记--盒子君hzj】
(2)赋值语法方法二:
name hzj={1,2};
注意:定义是单独的,赋值如果是顺序的话可以和在一起写,不然就要分开写
类是一个模板,用于定义对象的,方法别称(函数|动词),属性别称(变量|名词)
在设计、定义、使用一个类的时候,应该让每个组成部分简单到不嫩挂在简单是最好的,越简单越灵活
**(1)使用上**:类似于结构体和定义的关系,先定义结构体再进行结构体的使用,
类似的,先定义一个类,再对类进行使用
**(2)功能上**:结构体只能进行变量数据类型(属性)的组合,
但是类不但可以进行变量数据类型的组合,还可以对功能相关的函数(方法)进行组合
【防盗标记--盒子君hzj】
**(3)实际上**,类是结构体慢慢进化而来的,更具有灵活性,再类中通常把变量成为属性,
把函数称为方法。
类仅仅是对象的一个雏形模板(必须内容干干净净的),经过过个类的组合完成对对象的描述,
类决定将一个对象打造成拥有什么功能,属性
联合与结构体有很多相似的地方,也可以容纳多个不同类型的值,
但是联合每次只能储存这些值的某一个,即存放一个值会把上一个值覆盖掉,
用于密码设置等(结构体可以定义多个密码,但是联合只能定义一个)
【防盗标记--盒子君hzj】
union mima
{
int birthday;
char user;
int &c;
};
mima mima_1;
mima_1.birthday=19961220;【把19961220存入birthday变量中】
mima_1.user="hzj" 【这时候把hzj存入user的时候会把原来的birthday变量覆盖,做到一改全改】
枚举类型用于创建一个可取值的列表,取值也只能在这个列表里面,
否则会出错,编译器会把枚举的元素按照0~N进行顺序排列,
枚举其实是方便给人看的,实质内容也是0~N(功能比数组少一点,但是安全性也会高一点)
最好配合switch语句进行使用,避免了字符串的单引号的使用
enum weekdays
{
monday,
tuesday,
wednesday,
thursday,
friday
};
weekdays today
【防盗标记–盒子君hzj】
today monday
都是宏定义的意思,const比define更高级就行了,**const是静态变量,define是常量**
功能:作用是为一个类型去一个别名;类似于define,但是**define是针对与常量的,而typedef是针对一个类型的**
--typedef int* intpointer;【把int*取别名intpointer】
--intpointer a 【从此可以直接用intpointer定义一个指针变量a】
成员访问运算符“*” --用于把指针变量的地址转化成变量,进行运算
【可以这么理解加*往上层走,加&往下层走】
使用方法:对象.函数(行为),如:cin.peek();意思是cin这个流对象调用了peek()这个函数【区别于C语言中的主函数调用子函数】
"->"解引用符 --针对地址
【指针用"->",对象用"."】
1、在C语言中“<<”是左移操作符
2、在C++语言中“<<”是一个流操作符
【防盗标记--盒子君hzj】
3、这两个流操作符调用了输入输出对象,已经做好了重载,能自动识别整形、浮点型、字符型等等数据结构
4、C语言和C++语言的“<<”含义是不一样的,C++语言对这个"<<"进行了重载,运行C文件是左移操作符,运行C++文件是流操作符
作用:告诉编译器这个函数是存在在哪里的,或者是属于哪个类的,如
std::cout<< <<
尺寸运算符"sizeof"
.
.
1、流有数据流、输入\输出流、视频流,程序流,流程图等等
2、输入流类比:程序指令输入,从键鼠到程序内部,这就是一个输入流,cin<<.....<<
3、输出流类比:屏幕显示输出,从程序内部到屏幕,这就是一个输出流cont<<......<<
print是面向过程的输出,本质是一个函数
cout是面向对象的输出,本质是一个类(输出流对象)
【防盗标记--盒子君hzj】
cin.ignore(7) 忽略输入的前7个字符
cin.getline(buf,10) 只取输入的10个字符,存放在buf的数组(缓冲区)里
cin.gcout() 检测输入了多少数目的字符
cin.read(buf,10) 只取输入的10个字符,存放在buf的数组(缓冲区)里
cout.write(buf,10) 从缓冲区输出了10个数目的字符
cout<
.
.
#include这个库是输入输出流的库
#include这个库是字符串的库,调用如:std::stream str
这些标准库的**内建功能**非常多,百度一下,绝大部分的功能都能实现的如
--提取字符串
--比较字符串
--添加字符串
【防盗标记--盒子君hzj】
--搜索字符串
argc:整形变量,含义是传入程序的参数数量,包含本身
argv[]:字符指针数组,含义是对应指针指向的文件
ifstream in(char*filename,int open_mode)
--ios::in 其中ios是命名空间,只可读取文件
--ios::out 只可写入
--ios::binary 以二进制文件打开(如exe文件,还有一种形式文本形式)
--ios::app 在文件末尾追加一个写入的所有数据
--ios::trunk 删除所有文本的所有文件
--“|”用这个分隔符,同时实现多种打开方式,因为in\out这些指令是枚举变量,事先已经由默认值了
(::前面是一个命名空间,后面是他对应的函数)
.
.
.
这里是针对函数的传入参数总结的
【防盗标记–盒子君hzj】
默认情况下,C/C++中,被传递到函数的只是变量的值,永远不可能是变量本身
1、函数定义上
**int changeage(int age)**
2、函数调用上
**int changeage(age)**,传入的参数为整型数据age
【这样传入的值和调用的变量对应的上】
.
想要绕开"传值"的问题,最好的办法是拿到变量的地址,变成传址问题,想要获得某个变量的地址很简单,只需要在变量前加上"&"取地址符,如&age。
1、函数定义上
**int changeage(int *age)** 【这里说明实参输入是地址,因为要赋值在指针上】
2、函数调用上
**int changeage(&age)**传入参数为age的地址&age
【这样传入的地址刚刚和调用的指针对应的上】
传址注意:如果传过去的是地址必须要用"*"进行解引用,才能操作进行运算,除非你要修改地址
.
和传址的过程是一样的,形式有点不一样而已
1、函数定义上
【防盗标记--盒子君hzj】
**int changeage(int &age)**【这里说明实参输入是地址】
2、函数调用上
**int changeage(age)**【实质传入参数为age的地址&age,这里系统会自动的把age变成他对应的地址,但是优点在于运算是可以把age当变量使用】
1、形参和实参的不同,形参是被调函数的形式参数,实参是运行函数中实际参数
2、传值调用并不会改变原来的变量的值,但是传址调回用会改变原来的值,因为本质是改地址底层的东西
3、值传递是安全的,址传递是危险的
4、和传址有点迷惑性的
.
.
在静态变量前加入(变量数据类型)
强制改变变量的的数据类型,来对得上程序的数据结构要求
(int)、(float)、(double)、(class name*)、(char)等等
9/5.0输出的是整数,9。0/5.0输出的是浮点数
【防盗标记--盒子君hzj】
.
.
实质就是用同样的名字再定义一个有着不同参数但有着同样功能用途的函数(如同一个人,能完成不同的事情一样)
重载可以重载不同数目的参数,也可以重载不同的数据类型
改变函数传入的形参数据结构,同时对同一名字而不同数据结构的函数进行声明,系统会自动识别
改变函数传入的形参的数目,同时对同一名字而不同数据结构的函数进行声明,系统会自动识别
简化工作的编程工作,提高了程序的可读性,所以重载不是面向对象的特征
重载机制可以允许定义同名的多个函数(方法),只是这些函数的输入参数必须不同(可以参数的数据类型不同,也可以参数的数量不同),
编译器会自定识别,因为编译器是根据不同的参数输入区分不同的函数(方法)的
注意:重载只能在类本身新定义的函数中进行重载,不能子类中先集成基类的函数再对该继承的函数进行重载,这样会出错的,重载机制只适合用于新定义的函数
【防盗标记--盒子君hzj】
注意区分重载机制和覆盖机制,及其两个机制的作用
1、重载的定义
重新赋予新的含义,函数重载就是对函数重新赋予新的含义,运算符重载就是对运算符重新赋予新的含义
2、运算符重载的方法:
先定义一个重载运算符函数,在执行被重载的运算符时,系统会自动调用该函数,实现相应的运算
3、运算符重载和函数重载的关系:
运算符重载是通过定义函数实现的,所以运算符重载实质上是函数的重载
4、重载运算符 函数格式一般如下:
函数类型 operator 运算符名称(形参列表)
{
对重载运算符的实现过程
}
例子:把加法运算符重载成减法运算符
【防盗标记--盒子君hzj】
int operator +(int a,int b)
{
return(a-b);
}
5、优点:
用重载运算符代替了函数调用的过程,可视化程度更高,仅仅关注运算符的功能就行,不用关心运算符功能的实现
6、注意:
1、C++不允许用户及定义新的运算符,只能对已有的运算符进行重载
2、以下蜈蚣丸运算符是不允许重载的。
--"." 成员运算符
--"*" 成员访问运算符
--"::" 作用域运算符
--"?:" 条件运算符
--"sizeof" 尺寸运算符
3、重载不能改变运算符对象(操作数)个数
4、重载不能改变运算符的优先级别
5、重载不能改变运算符的结合性
6、重载运算符函数不能有默认的参数
7、重载运算符必须和用户定义的自定义类型的对象一起使用,其参数必须有一个类的对象或者引用。(这个约定是为了防止程序员该标准类型结构的运算符性质)
8、只有在经常使用,很有必要的时候才重载运算符,因为别人读程序,重载运算符不好理解
9、重载运算符尽量不要改变他原有的意义,最好是在原有的意义上增加功能
通过重载"<<"操作符来实现print打印输出的功能
1、多态性的解释:
用同一个名字定义冉函数,当调用同一个名字的函数的时候,却执行不同的操作,从而实现了一个接口,多钟方法(函数),理解上可以康丽洁为重载函数的升级版
2、多态性是如何实现的
【防盗标记--盒子君hzj】
--编译时的多态性:重载函数
--运行时的多态性:虚函数
当多个对象同时需要某个变量的数据,而该变量数据又不属于某个类class
解决方法一:可以通过吧这个数据定义成全局变量,这样可以解决这个问题,
但是这样存在一个不安全性,因为虽然满足了每个对象的访问级别问题,
但是若果每个对象都能修改这个变量,万一出错就找不到源头,
所以我们不建议在非必要的时候声明使用全局变量
解决方法二:
C++允许我们把一个或者多个变量过着函数声明属于某个类,而不仅仅是该类特有的变量或者函数--静态变量
在它的声明前面加上static保留字就可以了,声明可以在类中的任何位置,包括:public\protected\private中
(1)可以使用普通函数的调用语法进行调用,但是不建议,如:objectName.methodName();
(2)坚持使用静态类的调用语法:ClassName::methodName();
(1)static既可以用于变量,和可以用于函数【这就是比全局变量好的地方,static静态变量可以认为是一个全局变量的功能,只是更强大了】
(2)记得要在类声明的外部对静态 属性(变量)做出声明,意思是静态变量要做两次声明【就像声明全局变量一样】,这么做是为了给静态变量分配内存
(3)静态成员是所有对象都可以共享的,所以不能在静态方法里访问非静态的元素【静态方法优先级是比较低的】
(4)非静态方法可以访问类的静态成员,也可以访问类的非静态成员
1、程序员可以在没有创建任何对象的情况下调用这个变量和函数【访问级别层面】
2、可以让有关的数据在所有的对象中进行共享 【数据层面】
【防盗标记--盒子君hzj】
为了是编译器有选择的调用覆盖的内容的方法(函数 )【相当于调用的优先级提高】
假如cat和dog是pet的子类,基类中有一个函数play(),
子类cat和dog也有对应的play()并对基类的play()进行了覆盖,
如果在主程序中定义pet *pointer=new cat,并执行cat->play();
结果是输出了pet.play()的 内容。这是不对的
虚方法是继承的,如果在基类里把某个函数或者变量声明为虚方法(函数)
,在子类中就不可以在一次声明是虚方法(函数)了,
因为本来已经继承了,已经是虚函数了
在变量或者函数定义前加上virtual保留字
程序员无需顾虑一个虚函数会咋子其某个子类中编辑一个非虚函数
(1)如果某个函数拿不准要不要声明为虚方法,那么就把这个函数声明为虚方法
(2)虚方法可能会使程序运行的慢一点,但是安全性高,天使过程不会出现奇怪的现象
**纯虚函数【最抽象的函数,什么都不做就是什么都做了】**
在设计一个多层次 类继承关系时常常用到
【防盗标记--盒子君hzj】
功能:告诉编译器不要浪费时间在这个类中寻找实现函数了,只有在继承的时候才会有实现过程
语法:在声明一个虚方法的基础上,在原型的末尾加上“=0”
virtual void eat()=0;
.
.
.
静态内存就是包括我们此前一直使用的东西:变量(包括指针变量)、固定长度的数组、给定类的对象。我么可以可以根据变量名字和地址类访问设使用他们
(1)我们不得不在编写成虚的时候就分配一块足够大的内存给变量,这会消耗大量的内存
(2)一看程序运行起来,不管实际情况如何,变量占用的内存都是一样的,这也会到时有可能使内存溢出,导致数据错误
在很多时候,需要内存数据量的大小是无法事先完全知道的,除了用报错和限制取值范围的方法,这时候就需要用到动态内存管理
动态内存支持程序员创建和使用根据具体需要扩大和缩小的数据结构,他们仅仅受限于计算机的硬件内存大小的系统的特殊约束
动态内存是有一些没有名字,只有地址和内存块构成的,这些内存是只有在程序运行期间才会动态分配的
动态内存是有标准C++库的“内存池”管理的,从内存池申请一些内存需要使用new语句,
它将根据我们提供数据类型分配一块大小合适的内存(只要我们有足够大的内存空间),
new语句将会返回性分配地址的起始地址
【防盗标记--盒子君hzj】
如果计算机的内存已经满了,new语句就会抛出std::bad_alloc的异常警告,为了避免这种情况我们用new申请了一块内存后要用delete把他归还给内存池,
同时还要把用的指针变量设置为null,null指针的含义是不指向任何地址的指针【就是空指针】,这样避免数据泄露
例子:
int *i=new int; 【给指针变量i申请一块整型数据类型的内存空间,指针变量i存放着这块地址的手地址值】
i=null; 【设置指针为空指针】
delete i;
1、功能:动态创建过释放一个内存空间,避免运行的时候因为内存不足出错,指针是一种专门用来保存内存地址的数据类型,
方法一:我们以前使用指针的常用的做法是:创建一个普通变量,在创建一个指针变量,把普通的变量的地址赋给一个指针,然后我们就可以用指针变量铜鼓操作地址去访问这个变量了
方法二:在没有创建变量的情况下为有关数据分配内存:即直接创建一个指针变量并让它指向新分配的内存快
int *pointer=new int; 【new用于创建一个内存块,创建一个整形的内存块并用*pointer指向它】
*pointer=110;
std::cout<<*pointer;
delete pointer; 【delete用于删除一个内存块】
【新的C++新的两个保留字new和delete,程序中每一个new操作都要有一个delete操作与之对应,因为程序不会自动释放内存,会造成程序泄露】
在程序运行的时候让用户输入一个值自定义数组的长度,int a[???]:
int *x=new int[10]; 【动态分配一个整型数据的数组内存给指针数组变量x】
x[0]=45; 【通过数组下标的方式访问指针数组变量x】
【防盗标记--盒子君hzj】
x[1]=100;
删除一个动态数组,要比普通删除一个变量复杂,普通删除一个变量仅仅需要删除该一个变量的地址就行,二删除一个数组是要删除整个数组中所有变量的地址
方法:delete[]x;
不是所有系统都想windows一样经常重启,有些像linux系统用于服务器的几年都不关闭的,经常使用new申请内存又不释放,会大量占用计算机的内存,导致系统崩溃
避免内存泄露的推荐做法:
int *x;
x=new int[1000];
delete[] x;
x=NULL;
这么做已经把这块动态内存的地址存放的x彻底还原进去内存池了
.
.
编写的程序越多越复杂,就需要用到命名空间,命名空间其实是由用户自己制定义的范围,
同一个命名空间内的东西只要独一无二就可以的,如果某个程序有许多不同的头文件或者已经编译的文件,
而它们有各种声明了许多东西,这时候命名空间可以提供保护,以防变量及函数冲突,
这样不同命名空间里面就可以拥有相同的变量名和函数名了
【防盗标记--盒子君hzj】
这是一个命名空间的概念,作用是把C++标准库中所有的标志符(类函数、对象)都定义在同一个特殊的命名空间下,这样可以避免全局变量、局部变量等的冲突
先写出关键字namespace,在写出空间名字,最后用一堆花括号把命名空间里面的东西括起来
namespace name
{
.......
}
(1)在最后面不用加分号
(2)如果在程序开头没有写using namespace std;这个指令,还有一个补救的方法:std::cout语法来调用特定的输出流,std::在大型程序中是很有必要的
把实现的效果划分为多个部分(模块),每个模块写在一个文件里面,
这样把多个模块搞到多个文件中,用编译器把文件重新组合一起实现功能。
系统头文件功能:声明C++标准库文件 如:#include
提供必要的函数声明,变量声明、类声明,使用第三方库声明,
但是千万不要在头文件里面写程序的实现,程序的实现写在C/C++文件里面,如:#include“fish.h”
(1)自定义头文件一般都放在一个头文件里进行声明,再调用这个头文件就行了,这样避免重复包含和漏包含的情况,而且会专门创建一个目录(文件夹)分开存放这些头文件,易于查找
【防盗标记--盒子君hzj】
(2)头文件里面尽可能多的注释,因为头文件会被很多文件引用,声明的东西应该描述的更清晰
.
.
泛型编程技术支持程序员创建函数和类的模板(template),而不是具体的函数和类
适用范围:
当程序员需要用到这些函数中的某一个是,编译器讲根据模板马上生成一个能够对特定数据类型进行处理的代码版本,这样允许程序员使用一个解决方案解决多个问题。
标准模板库(STL)
因为return是用来推出程序并返回错误信息的,其中return 0代表程序运行没有问题
要对数据的输入输出做合法性检查(特别是用户输入的数据),以免输入错误及系统崩溃,检查的是数据类型和取值范围(正负数、特定值)、参数个数等等
这样做事比较耗内存,但是大大增加了程序的健壮性(减少缓冲区溢出的问题)
解决办法:
1、使用switch语句检查特定值
2、用if语句做范围限幅
【防盗标记–盒子君hzj】
–有时候内存不够大也会出错
–或者缓冲区不够大
–或者数据类型不对应【重载能够解决】
–狂按enter键,触发了后面的程序(小孩子)
–系统的应用软件崩溃检查
–面对过程的把实现过程封装起来
–面对对象的把对象封装起来
–面对模块的把组件和一个一个程序文件封装起来
封装程度越高,越高级的程序语言,运行效率越低,要求的硬件越高 (因为要考虑通用性,会预先定义很多东西)
for(int i=0;i<10;i++)