VC++入门经典学习笔记模板.docx
- 文档编号:28596147
- 上传时间:2023-07-19
- 格式:DOCX
- 页数:48
- 大小:39.74KB
VC++入门经典学习笔记模板.docx
《VC++入门经典学习笔记模板.docx》由会员分享,可在线阅读,更多相关《VC++入门经典学习笔记模板.docx(48页珍藏版)》请在冰豆网上搜索。
VC++入门经典学习笔记模板
VC++入门经典学习笔记
一函数
这里是源码:
A.函数是具有用途的自包含的代码块。
函数名既是函数的标识,用来在程序中调用函数。
如果函数名不在名称空间中定义,它就是全局的,否则就要用名称空间的名称来限定他。
B.函数的主要优点之一是根据需要可以在程序的不同位置执行任意次。
如果不能将代码块封装到函数中,则程序将最终成为庞然大物,因为那样通常需要再程序的不同位置复制相同的代码。
使用函数还可以将程序分为易于管理的代码块,以方便开发和测试,复杂的大型程序如果包含几个小代码块,就比编写为一个大代码块更容易理解和测试。
C.函数头
intnum(doublea,intb);
本行由三部分组成:
a.返回值的类型(本例中int)
b.函数名(本例中num)
c.圆括号中的函数形参(本例中是a和b,分别为double和int类型)
注意:
函数头末尾和函数体右大括号后面都不需要分号。
如果函数没有返回值,则由void来指定返回类型。
(voidmyNum(inta));
简单介绍完函数,下面其实是好几个例子组成的:
下面这是main主函数和一些要调用函数的声明:
#include"stdafx.h"
usingstd:
:
cin;
usingstd:
:
cout;
usingstd:
:
endl;
//1.值传递(passbyvalue)
int_value(inta,intb);
//2.地址传递(passbypointer)
int_pointer(int*a);
//3.引用传递(passbyreference)
int_reference(int&a,int&b);
//4.函数返回指针
int*_rpointer(inta,intb);
//5.函数中的静态变量
int_countNum(inta,intb);
//6.递归函数调用
int_chengNum(intn);
int_tmain(intargc,_TCHAR*argv[])
{
inta{5};
intb{5};
int_vNum{};
int*_pNum{&a};
int_rNum{};
int*_pRNum{};
int_cNum{};
//1.值传递
printf("调用传值前:
a=%d,b=%d,vNum=%d\n",a,b,_vNum);
_vNum=_value(a,b);
printf("传值后:
a=%d,b=%d,vNum=%d\n",a,b,_vNum);
//2.地址传递
printf("调用传地址前:
a=%d,*_pNum=%d\n",a,*_pNum);
*_pNum=_pointer(&a);
printf("传地址后:
a=%d,*_pNum=%d\n",a,*_pNum);
//3.引用传递
printf("调用传引用前:
a=%d,b=%d,_rNum=%d\n",a,b,_rNum);
_rNum=_reference(a,b);
printf("传引用后:
a=%d,b=%d,_rNum=%d\n",a,b,_rNum);
//4.函数返回指针
_pRNum=_rpointer(a,b);
cout<<"_pRnum="<<*_pRNum< delete_pRNum;//释放掉内存 _pRNum=nullptr; //5.函数中的静态变量 _vNum=_countNum(a,b); _vNum=_countNum(a,b); _vNum=_countNum(a,b); _vNum=_countNum(a,b); //6.递归 intc{5}; _cNum=_chengNum(c); cout< "<<_cNum< system("pause"); return0; } 实现被调用的函数 1.给函数传递实参: int_value(inta,intb) { a+=5;//改变形参a的值 b+=5;//改变形参b的值 returna+b; } 2.地址传递 当使用指针作为实参时,按值传递机制仍然像以前一样工作。 但指针是另一个变量的地址,如果创建该地址的副本,则副本仍然指向相同的变量。 以指针作为形参可以使函数处理调用者实参。 int_pointer(int*a) { //return&a; *a+=5;//改变指针指向的地址 return*a; } 3.引用传递 给函数传递实参的第二种方法: 形参其实是引用被传递实参的别名,该机制不再复制所提供的实参。 允许函数直接访问调用函数中的实参。 当使用类类型对象时,对函数使用引用形参具有特殊的意义。 对象可能会很大,很复杂,此时复制过程中,可能会耗费很多时间。 在这样的情况下,使用引用形参可以大大加快代码的执行速度。 可以给函数的形参使用const修饰符,以告诉编译器我们不想以任何方式修改这个形参。 int_reference(int&a,int&b) { a+=5;//改变形参a的值 b+=5;//改变形参b的值 returna+b; } 4.函数返回指针 返回地址的规则: 永远不要从函数中返回局部自动变量的地址。 这样做很危险的,因为: 函数_rpointer(a,b)中的变量num是在该函数开始执行时创建的,并在该函数退出时被销毁,因此指针ptr指向的内存不在包含原来的变量值。 先前分配给num的内存现在可能用于其他目的。 改正: 我们的意图是返回指向某些有用数据的指针,以便最终能够返回多想数据。 一种方法是动态分配内存。 使用操作符new,可以在空闲存储器中创建一个新变量,该变量一直存在,知道最终被delete销毁,或者知道程序结束。 注意: 动态分配内存时,每次调用该函数时都要多分配一些内存。 当然不需要内存时,主调程序需要将其删除,但实践中 人们很容易忘记这么做,结果就是空闲存储器的内存被逐渐消耗,知道某个时刻内存用尽且程序失败。 这类问题称为内存泄漏。 int*_rpointer(inta,intb) { //intnum=a+b; //num+=10; //改正后 int*num{newint{}}; *num=a+b; *num+=10; returnnum; } 5.函数中的静态变量 有些时候用自动变量不能完成的。 例如不能计算调用函数的次数,因为无法再多次调用中累积数值。 有多重方法可以解决该问题。 例如,可以使用引用形参来更新调用程序中的计数器,但如果程序中的许多不同位置都调用该函数,这种方法将无济于事。 还可以使用在函数中递增的全局变量,但这样做是有风险的,因为程序中任何位置都可以访问全局变量,他们非常容易被以外修改。 在具有多个访问全局变量的执行线程的应用程序中,全局变量同样是危险的,因此必须特别注意管理从不同线程中访问全局变量的方式。 当多个线程都可以访问某个全局变量时,必须处理的基本问题: 一个线程使用全局变量时,另一个线程可以修改该变量的值。 在这样的情况下,最好的解决方案是完全避免使用全局变量。 函数内静态变量的初始化仅仅发生在第一次调用该函数的时候。 事实上,初次调用函数时该变量包含的任何值都可以在下次调用时使用。 关于Static关键字 a.静态变量,分配在静态存储区,在数据段中。 函数退出之后,变量值不变。 b.作用域,全局的静态变量、静态函数只能在本文件中使用。 (不同于一般全局变量) 局部的静态变量同函数的局部变量 注: 局部静态变量占用内存时间较长,并且可读性差,因此,除非必要,尽量避免使用局部静态变量。 作用: a、非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 b、静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件(即声明了该变量的CPP文件,或包含该变量声明头文件的CPP文件)中不能使用它。 在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。 int_countNum(inta,intb) { a+=5; b+=5; staticintcountNum{}; countNum++; cout<<"调用次数: "< returna+b; } 6.递归函数 递归函数调用: 当函数包含自身的调用时,称之为递归函数。 递归的函数调用也可以是间接的,即函数fun1 调用函数fun2,后者再调用fun1。 递归可以看做实现无穷循环的一种方法,如果我们不小心,就会发生这种情况。 无穷循环将锁住计算机,需要按Ctrl+Alt+Del组合键才能终止程序,这永远是件非常令人讨厌的事情。 避免无穷循环的前提是函数包含某种使递归调用过程停止的方法。 在物理和数学方面,有许多问题可以被视为包含递归。 整数的阶乘就是个简单的例子。 对于给定的整数N来说,其阶乘就是乘积1*2*3*。 。 。 *N 注意: 除非遇到的问题特别适用于使用递归函数,或者没有明显的替代方法,否则使用其他方法一般(如循环)会更好。 使用循环比使用递归的函数调用的效率更高。 在深度适中的递归调用中,系统开销也可以大大超过使用循环时的开销。 当然这样说的意思不是我们永远不应该使用递归。 当问题适于用递归函数调用来解决时,递归就是非常强大的技术可以大大简化代码。 int_chengNum(intn) { staticintcountNum{n};//声明一个静态变量; countNum*=(n-1); cout< if(n>2) return_chengNum(n-1); else { returncountNum; } } 源码下载: 二结构和类 1.自定义数据类型 C++中的结构: 结构是使用关键字struct定义的用户定义类型。 结构起源于C语言,C++继承并扩展了结构。 C++中的结构在功能上可以由类代替,因为任何使用结构能够做到的事情都可以使用类做到。 但是因为Windows是在广泛应用C++之前用C语言编写的,所以结构遍布在Windows编程的各个方面。 今天,结构仍然被广泛使用,因此我们确实需要了解结构。 2.结构的概念 考虑一下要描述像一本书这样简单的事物需要多少信息。 我们首先可能想到书名,作者,出版社,出版日期,页数,定价,主题或分类以及ISBN号,还可能不太困难地就想到一些其他信息。 我们可以指定相互独立的变量来容纳描述一本书所需的每项信息,但更希望能够使用一种数据类型来包含所有这些信息。 这正是结构能为我们做的事情。 3.定义结构 假设只需要在书的定义中包括书名,作者,出版社和出版年份。 structBook { chartitle[80]; charauthor[80]; charpublisher[80]; intyear; }; 这里的代码没有定义任何变量,但实际上创建了一种新的类型,该类型的名称是BOOK。 关键字struct将BOOK定义成结构,构成本类型对象的元素是大括号内定义的。 结构体内的元素可以是除所定义的结构类型以外的任何类型。 例如,BOOK的结构定义中不能包括类型为BOOK的元素。 我们可以认为这是一种局限性,但BOOK定义中可以包括BOOK类型变量的指针。 创建其他类型变量的方式来创建BOOK类型的变量: BOOKnovbel;//声明一个BOOK类型的变量novbel. 4.初始化结构 第一种将数据存入结构成员的方法,是在声明语句中为结构体成员定义初始化。 Booknovel { “PanelessPrograming”, "I.c.Fingers", "GutterPress", 1981 }; 这些初始化值位于初始化列表内,相互之间以逗号分开,这种方式与为数组成员定义初始值的方式完全相同。 5.访问结构的成员 为了访问结构各个成员,可以使用成员选择操作符”.”,有时称之为成员访问操作符。 如果想修改Novel结构的Year成员可以这样写: novel.year=1988; 1 6.RECT结构在windows程序中,矩形用的很多。 因此,包含在windows.h的windef.h头文件中有一个预定义的RECT结构,,其定义本质是 structRECT { LONGleft; LONGtop; LONGright; LONGbottom; }; MFC(微软基础类库(英语: MicrosoftFoundationClasses,简称MFC)是一个微软公司提供的类库(classlibraries),以C++类的形式封装了WindowsAPI,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。 其中包含的类包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类。 )MFC也定义了等价于RECT结构的CCRect类。 当我们理解类之后,将优先使用CRect大类而非RECT结构。 CRect类提供了很多处理矩形的函数,在使用MFC编写Windows程序时将大量使用这些函数。 7.使用指针处理结构 可以创建指向结构类型对象的指针。 windows.h中声明的许多处理RECT对象的函数都要求实参是指向RECT的指针,因为这样可以避免给函数传递RECT实参时复制整个结构的系统开销。 RECT*pRect{};//声明一个指针指向RECT 1 假设已经定义了一个RECT对象&aRect,那么可以使用通常的方式将aRect变量的地址赋予pRect指针: pRect=&aRect; 1 struct不能包含与被定义结构类型相同的成员,但可以包含指向struct的指针,其中包括指向相同类型struct的指针。 structListElement { RECTaRect; ListElement*pNext; } 8.通过指针访问结构成员 RECTaRect{0,0,100,100}; RECT*pRect{&aRect}; 1 2 第一条语句声明并定义了一个RECT类型的对象aRect,将第一对成员初始化为{0,0},将第二对成员初始化为{100,100}。 第二条语句将pRect声明为指向RECT类型的指针,并将其初始化为aRect的地址。 现在,可以用下面的语句,通过指针访问aRect的成员: (*pRect).top+=10; 1 这里使用的通过指针访问struct成员的方法看起来相当笨拙。 这种操作在C++中出现得相当频繁,因此C++提供了一个特殊操作符,间接成员选择操作符(->)。 pRect->top+=10; 1 该语句更清楚地表示自己的用途。 在本书中经常会看到该操作符。 9.数据类型,对象,类和实例 基本类型的变量不能充分模拟现实世界中的对象或虚拟的对象。 例如,很难用int模拟一个箱子,但可以使用struct成员为这样的对象定义一组特性。 如下所示,可以定义length,width和height这3个变量来表示箱子的尺寸,并将它们作为Box结构的成员捆绑到一起: structBox { doublelength; doublewidth; doubleheight; }; 有了名为Box的新数据类型的定义之后,就可以像定义基本类型变量那样定义该类型的变量。 在程序中,可以创建,处理和销毁任意数量的Box对象。 这意味着可以使用struct来模拟对象,并围绕对象编写程序。 因此,这就是面向对象编程,对吗? 对,但不完全对。 面向对象编程(OOP)基于与对象类型相关的3个基本概念,即封装,多态性和继承性,而我们目前所看到的不完全与之吻合。 在C++中,struct的概念远远超出了C语言中原来的struct概念,它现在合并了类的面向对象思想。 类的思想–可以创建数据类型并像使用已有类型那样使用,对C++而言非常重要,因此该语言引入了一个新关键字class来描述类这一概念。 在C++中,除了成员的访问控制以外,关键字struct和class几乎是等同的。 保留关键字struct是为了向后兼容C语言,但使用struct能实现的一切都可以用类来实现,而且类可以比struct实现更多的功能。 定义表示箱子的类: classCBox { public: doublem_length; doublem_width; doublem_height; }; 与定义Box结构的情况类似,将CBox定义成类时,实质上是在定义新的数据类型。 仅有的区别是使用了关键字class代替struct,还在类成员的定义前面使用了后跟冒号的关键字public。 作为类组成部分被定义的变量称为类的数据成员,因为他们是存储数据的变量。 public关键字提供了区别结构和类之间的线索。 以该关键字定义的类成员通常是可以访问的,其访问方式与访问结构成员相同。 默认情况下,类成员一般是不可访问的,而是私有的(private)。 为了使类成员可访问,就必须在他们的定义前面使用关键字public。 结构成员默认是共有的。 类成员默认情况下之所以是私有的,一般是因为类对象应该是自包含实体,这样的数据使对象应该被封装起来,并且只能在受控制的情形下修改。 公共的数据成员是非常少见的例外情况。 MFC采用了在所有类名称以C作为前缀的约定,因此我们也要养成这样的习惯。 MFC还给类的数据成员添加m_前缀,以便将他们与其他变量区别开来。 可以像下面这样,声明一个表示CBox类类型的实例bigBox CBoxbigBox; 1 10.类的起源: 类的概念是以为英国人为使普通人保持心情愉快而发明的,它源于”知道自己在社会中的地位和作用的人们,生活将比那些对此茫然无知的人更感到安全和舒适”这一理论。 著名的C++发明者丹麦人BjarneStroustrup在剑桥大学期间学到了深奥的类概念,并非常成功地将之应用到他的新语言中。 类通常都有非常精确的任务和一组可以执行的动作,从这一点来讲,C++中的类与英语原意相同。 但是,C++中的类与英语原意是有区别的,因为他们很大程度上专注于实现工作类的价值。 实际上,在某些方面他们甚至与英语原意相反,因为C++中的工作类往往位于那些完全不做任何事情的类背后。 11.类的操作 在c++中,可以创建新的数据类型–类,来表示任何希望表示的对象。 类(以及结构)不仅限于容纳数据,还可以定义成员函数,甚至可定义在类对象之间使用标准C++运算符执行操作。 还可以在CBox类中实现使box相加,相减乃至相乘的操作。 事实上,几乎任何在box上下问中有实际意义的操作都可以实现。 这里谈论的是令人难以置信的强大技术,它使我们采用的编程方法产生了重大变化。 我们不在根据本质上与计算机相关的数据类型(整数,浮点数等)分解问题,然后编写程序,而是根据与问题相关的数据类型(换一种说法就是类)进行编程。 12.类的相关术语 类是用户定义的数据类型。 面向对象编程(OOP)是一种编程风格,它基于将自己的数据类型定义成类的思想,这些数据类型专用于打算解决的问题的问题域。 声明类的对象有时称作实例化,因为这是在创建类的实例。 类的实例称为对象, 对象在定义中隐式地包含数据和操作数据的函数,这种思想称为封装。 13.理解类 类是用户定义的数据类型的说明,其包含的数据元素可以是基本类型或其他用户定义类型的变量。 类的数据元素是单数据元素,数组,指针,几乎任何种类的指针数组或其他类的对象,因此在类类型可以包括的数据方面有非常大的灵活性。 类还包含通过访问类内的数据元素来处理本类对象的函数。 因此,类组合了构成对象的元素数据的定义和处理奔雷对象中数据的方法。 类中的数据和函数称为类的成员。 奇怪的是类的数据项称为数据成员,函数的类成员称为函数成员或成员函数。 类的成员函数有时也称作方法。 定义类时,就是在定义某种数据类型的蓝图。 我们没有实际定义任何数据,但确实定义了类名的意义--即类对象将由那些数据组成,对这样的对象可以执行什么操作。 如果要编写基本类型double的说明,则情况完全相同。 但我们编写的不是double类型的实际变量,而是这种变量的构成和操作的定义。 为了创建基本数据类型的变量,需要使用声明语句。 创建变量的情形完全相同。 14.定义类: 定义表示箱子的类: classCBox { public: doublem_length; doublem_width; doublem_height; }; 类名跟在class关键字后面,3个数据成员在大括号内定义的。 数据成员的定义使用我们已经很熟悉的声明语句,整个类定义以分号结束。 所有类成员的名称都是该类的局部变量。 因此,可以在程序中的其他地方使用相同的名称,包括其他类定义。 类的访问控制: public关键字决定着后面那些类成员的访问属性。 将数据成员指定为public,意味着在包含这些成员的类对象的作用于内的任何位置都可以访问它们。 还可以将类成员指定为private或protected,此时这些成员不能在类的外部访问。 事实上,如果完全省略访问说明,则成员的默认访问属性是private(这是类和结构之间的唯一区别--结构的默认访问说明符是public)。 15.声明类的对象 声明类的对象的方法与声明基本类型对象的方法完全相同。 因此,可以用下面的语句声明类类型CBox的对象: CBoxBox1; CBoxbox2; 1 2 box1和box2这两个对象都拥有各自的数据成员。 16.访问类的数据成员 可以使用访问结构成员时用过的直接成员选择操作符来引用类对象的数据成员。 17.对象成员的初始化 因为CBox对象的数据成员是public,所以在创建对象时,可以在初始化列表中指定他们的值: CBoxbox1{2.5,3.5,4.5}; 1 box1的成员按顺序获取列表的值,所以m_Length是2.5,m_Height是4.5。 如果在列表中提供的值少于数据成员的个数,未获取值的成员就设置为0。 CBoxbox2{2.5,3.5}; 1 也可以提示一个空列表,把所有成员都初始化为0: CBoxbox3{}; 1 18.初始化类成员 classCBox { public: doublem_length{1.0}; doublem_width{1.0}; doublem_height{1.0}; }; 初始化类成员的语法与普通变量相同,也是使用初始化列表。 初始化应用于所创建的任何CBox对象的成员,除非成员的值通过其他方式设置。 19.类的成员函数是其定义或原型在类定义内部的函数
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VC 入门 经典 学习 笔记 模板