??xml version="1.0" encoding="utf-8" standalone="yes"?>
static int n; //定义静态全局变量改ؓ
int n; //定义全局变量
E序照样正常q行?br />的确Q定义全局变量可以实现变量在文g中的׃nQ但定义静态全局变量q有以下好处Q?
]]>
VC ~译选项Q?/b>
调试ҎQ?/b>
1、?AssertQ原则:量单)
assert只在debug下生效,release下不会被~译?br />
例子Q?
char* strcpy(char* dest,char* source) { assert(source!=0); assert(dest!=0); char* returnstring = dest; while((*dest = *source )!= ‘\0? { ; } return returnstring; }
2、防御性的~程
例子Q?
char* strcpy(char* dest,char* source) { if(source == 0) { assert(false); reutrn 0; } if(dest == 0) { assert(false); return 0; } char* returnstring = dest; while((*dest = *source )!= ‘\0? { ; } return returnstring; }
3、用Trace
以下的例子只能在debug中显C,
例子Q?br />
a)、TRACE
CString csTest Q?“test”; TRACEQ“CString is Qs\n”,csTestQ;
b)、ATLTRACE
c)、afxDump
CTime time = CTime::GetCurrentTime(); #ifdef _DEBUG afxDump << time << “\n? #endif
4、用GetLastError来检返回|通过得到错误代码来分析错误原?br />
5、把错误信息记录到文件中
异常处理
E序设计时一定要考虑到异常如何处理,当错误发生后Q不应简单的报告错误q出程序,应当可能的惛_法恢复到出错前的状态或者让E序从头开始运行,q且对于某些错误Q应该能够容错,卛_讔R误的存在Q但是程序还是能够正常完成Q务?br />
调试技?/b>
1、VC 中F5q行调试q行
a)、在output DebugH口中可以看到用TRACE打印的信?br />b)?Call StackH口中能看到E序的调用堆?br />
2、当Debug版本q行时发生崩溃,选择retryq行调试Q通过看Call Stack分析出错的位|及原因
3、用映文件调?br />
a)、创建映文ӞProject settings中link,选中Generate mapfileQ输出程序代码地址Q?MAPINFO: LINESQ得到引出序P/MAPINFO: EXPORTS?br />b)、程序发布时Q应该把所有模块的映射文g都存档?br />c)、查看映文Ӟ见?通过崩溃地址扑և源代码的出错行”文件?br />
4、可以调试的Release版本
Project settings中C 的Debug Info选择为Program DatabaseQLink的Debug中选择Debug Info和Microsoft format?br />
5、查看API的错误码Q在watchH口输入@err可以查看或者@err,hrQ其中?hr”表C错误码的说明?br />6、Set Next StatementQ该功能可以直接跌{到指定的代码行执行,一般用来测试异常处理的代码?br />7、调试内存变量的变化Q当内存发生变化时停下来?br />
常见错误
1、在函数q回的时候程序崩溃的原因
a)、写自动变量界
b)、函数原型不匚w
2、MFC
a)、用错误的函数原型处理用户定义消息
正确的函数原型ؓQ?
afx_msg LRESULT OnMyMessage(WPARAM wParam,LPARAM lParam);
3、}慎用TerminateThreadQ用TerminateThread会造成资源泄漏Q不C不得Ԍ不要使用?br />
4、用_beginthreadexQ不要用Create Thread来常见线E?br />
参考资料:
《WindowsE序调试?br />
1、二q制U别的Y件复?/p>
2、与开发语a无关
3、符合面向对象标?/p>
4、可以实现进E间通信
6.this 指针用法:?3?当程序执行语句list elem(i);?pȝ对this指针q行了如下的~省赋?this=&list;
赋值成员函CD?此例在例63基础?:
void Assign(linear_list&);//说明语句;
void linear_list::Assign(linear_list&p)
{if(&p==this)
return;
nmax=p.nmax;
nelem=p.nelem;
list=new int[nmax];
for(int i=0;i<nmax;i++)
list[i]=p.list[i];
}
7.const,volatile对象和const,volatile成员函数
格式:const person per/volatile person per;
int func(int) const;/char func(int) volatile;
说明:1.普通对象既可以讉Kconst对象,又可以访问volatile对象;
2.const对象只能讉K用const修饰的成员函?
volatile对象只能讉K用其所长volatile修饰的成员函?
3.也可以同时说明ؓconst volatile对象或const volatile成员函数;
const volatile对象只能讉Kconst volatile成员函数;
const/volatile对象也能讉Kconst volatile成员函数;
8.不同l承方式的基cdzcȝ?br /> ------------------------------------------------
l承方式 | 基类Ҏ ?| zcȝ?br /> ------------------------------------------------
| public | public
公有l承 | protected | protected
| private | 不可讉K
------------------------------------------------
| public | private
U有l承 | protected | private
| private | 不可讉K
------------------------------------------------
| public | protected
保护l承 | protected | protected
| private | 不可讉K
------------------------------------------------
A:帮助理解Q?Q对于公有承方式:
a.基类成员对其对象的可见性:公有成员可见Q其他不可见。这里保护成员同于私有成员?br /> b.基类成员Ҏ生类的可见性:公有成员和保护成员可见,而私有成员不可见。这里保护成员同于公有成员?br /> c.基类成员Ҏ生类对象的可见性:公有成员可见Q其他成员不可见?br /> 所以,在公有承时Q派生类的对象可以访问基cM的公有成员;zcȝ成员函数可以讉K基类中的公有成员和保护成员。这里,一定要区分清楚zcȝ对象和派生类中的成员函数对基cȝ讉K是不同的?br /> 2) 对于U有l承方式Q?br /> a.基类成员对其对象的可见? 公有成员可见Q其他不可见?br /> b.基类成员Ҏ生类的可见性:公有成员和保护成员可见,而私有成员不可见
c.基类成员Ҏ生类对象的可见性:所有成员都是不可见的?br /> 所以,在私有承时Q基cȝ成员只能q接派生类讉KQ而无法再往下ѝ?br /> 3) 对于保护l承方式Q?br /> 与私有承方式相同,两者的区别仅在于对zcȝ成员而言Q对基类成员有不同的可见性?br /> B:帮助理解Q?) 公有l承Ӟ水^讉K和垂直访问对基类中的公有成员不受限制?br /> 2) U有l承Ӟ水^讉K和垂直访问对基类中的公有成员也不能访问?br /> 3) 保护l承Ӟ对于垂直讉K同于公有l承Q对于水q问同于私有ѝ?br /> 4) 对于基类中的U有成员Q只能被基类中的成员函数和友元函数访问,不能被其他的函数讉K?br /> C:帮助理解Q在公有l承Ӟzcȝ成员函数可访问基cM的公有成员和保护成员Q派生类的对象仅可访问基cM的公有成员?br />9.zcȝ构造函数和析构函数Q?br /> z构Q?br /> 1.一般格式: zcd (zcL造函数d数表):基类构造函?参数?),子对象名(参数?)
{zcM数据成员初始化}Q?br /> 2.调用序Q?a.基类的构造函数。b.子对象类的构造函?如果有的?. c.zcL造函数。 ?
10.多承:是指zcd有多个基cR?br /> 多承的构造函敎ͼ
《派生类名》(d数表Q:《基cd1》(参数?Q,《基cd2》(参数?Q,...
{zcL造函C}
11.虚基c:如果基类被声明ؓ虚基c,则重复承的基类在派生磁对象实例中只好存储一个副本,否则Q将出现多个基类成员副本?br /> 虚基c说明格式如下: virtual<l承方式><基类?gt;
class B:virtual public A
注意Qa.如果一个派生类有直接或间接的虚基类Q那么派生类的构造函数的成员初始列表中必d出对虚基cȝ调用Q如果未被列出,则表CZ用该基类的缺省构造函数来初始化派生类对象中的虚基cd对象?br /> b.虚基cȝ构造函数先于非虚基cȝ构造函数调用?br /> c.只有建立对象的那么个zcȝ构造函数调用虚基类的构造函敎ͼ而该zcȝ基类中所列出的对q个虚基cȝ构造函数的调用在执行中被忽略。 ?
12.q算W重载:
operator 函数用法Q?不能有下列字W:'::','.','*','->','? :')
1.一般:int class_name::operator <q算W?gt; (形参列表) (?2)
2.增量减量q算W? (?3,94,95,96)
a.一个增量运符重蝲为前|的成员函数:
int class_name::operator++();
b.一个增量运符重蝲为后|的成员函数Q?br /> int class name::operator++(int);
c.一个增量运符重蝲为前|的友元函数Q?br /> int operator ++(class_name&);
d.一个增量运符重蝲为前|的友元函数Q?br /> int operator ++(class_name&,int);
e.下标q算W:
int class_name::operator[](形参) //只能是非静态成员函敊W ?
f.函数调用q算W:
int class_name::operator()(形参?//只能是非静态函敎ͼ且不可以带有~省的参?br /> g.成员选择q算W:
class_name $/* class_name::operator->();
h.new deleteq算W:
void *class_name::operator new(siz_t,<arg_list>);
void *class_name::operator delete(void *,<size_t>);
new delete只能被重载ؓcȝ成员函数Q不能是友元。而且无论是否使用关键字static
q行修饰Q重载了的new和delete均ؓcȝ表态成员函数?br /> 对于typedef unsigned size_t;
在头文galloc.h,mem.h,stddef.h,stdio.h,stdlib.h均说明;
i.友元函数Q?br /> 可以是一个类的非静态函敎ͼ也可以是cȝ友元函数?br /> {friend complex operator+(complex&,complex&);
}Q?
以下五种q算W不说明成友元运符Q?br /> "=","()","[]","->","type";
j.转换函数Q?br /> class_name::operator type(); //type 是Q何一个合法的C++的类型名Q包括基本数据类型和导出数据cdQ以及由关键字const和volatile引出的表辄。)
//不带M参数Q也无返回值类型,Lq回type的倹{只能是cȝ成员函数Q不能说明ؓ友元q算W?br /> k.cȝ赋D与q算W重载:
person & person::operator=(person &p)
{dele Name;
Name=new char[strlen(p.Name)+1];
strcpy(Name,p.Name);
Age=p.Age;
Sex=p.Sex;
return *this;
}
典型例题。当用系l自带对象赋值的函数Q如果对象里有如 *Name 型的Q则赋值后会两个指针同时指向一个成员元素的地址Q当调用析构函数释放Ӟ会释放两ơ,多释放一ơ,而生错误,q个典型例题是用于把一个成员元素复制到另一个对象中Q不是单U移动指针,当调用析构函数时Q会释放两次?br /> l.重蝲函数Q系l仅对Ş参加以区别?br />13.虚函?br /> 一般情况下Q指向一个对象的指针Q不允许指向另一个对象,但指向基cd象的指针可以指向它的zc,q可以访问派生类中原基类成员?br /> 如果一个函C旦说明ؓ虚函敎ͼ则无明它的类被承了多少层,在每一层中该函数都保持该virturlҎ。且可以在派生类中对该函数省略virtual.
虚函数必Lcȝ一个成员函敎ͼ不能是友元,但它可以是另一个类的友元。虚函数不能是一个静态成员?br /> 讑֮l定方式QɽE序h灉|性,但执行效率低Q占用内存多.
14.抽象c:U虚函数
U虚函数的一般Ş式ؓQvirturl cd名(参数表)=0;抽象cM能申请对象?br />15.cdl构Q?br /> 1.函数模板Qtemplate <class 模板形参?gt;
q回值类?函数名(模板函数形参表)
{
函数体;
}
example:
template <class T>
void swap(T &.x,T&.y)
{T t;
t=x;x=y;y=t;
}
2.重蝲函数模板Q调用用ơ序Q?br /> 1Q寻找一个完全匹配的函数Q找刎ͼ调用之?br /> 2Q寻找一个函数模板,其实例化生一个匹配的模板函数Q找刎ͼ调用之?br /> 3Q寻N载函C有无通过cd转换后生参数匹配的函数Q若有,调用之?br /> 3.cL板:template <class 模板形参>
class cL板名
{
cMQ?br /> }
example: tempplate <class T>
class stack
{private:
T *date;
int top;
public:
isempty();
}
template <class T>
{...}
16.cL板的友元Q?br /> a.一般的cL板友元函数?br /> b.闭型的cL板友元函数。当用类型参数将cL板实例化为某个具体的模板cLQ该cL板所包含的友元函C随之实例化?br /> c.开攑֞的类模板友元函数?br /> 例一百二十一?
17.C++的I/O库
1. I/O标准类
-----------------------------------------
c++名字 | 讑֤ | C中的名字 | 默认的含?br /> -----------------------------------------
cin | 键盘 | stdin | 标准输入
-----------------------------------------
cout | 屏幕 | stdout | 标准输出
-----------------------------------------
cerr | 屏幕 | stderr | 标准错误
-----------------------------------------
clog | 打印?| stdprn | 打印?
-----------------------------------------
2。键盘输?br /> cin>>a>>b>>c; //Ctrl+zl止
cin.get(char &ch)//从输入流获取一个字W,不忽略空格Ctrl+zl止
cout.put(ch)//输出一个字W ?
EOF//其gؓ-1,相当于终止符
cin.geline(char *buf,int limit,Deline='\n')//bufZ个指针或数组Qlimit为字W个?Deline取字W指定结束符。作用:从键盘读入一串字W。结束用Ctrl+z.
cin.gcount()//q回getline()刚刚读过的字W个数
cin.read(char *buf,int size)//d指定数目的字W?br /> cout.write(const char *str,int n)//cout.write("string",strlen("string");则输出全部字W?br /> cin.peek()//q回输入的下一个字W,但是不提取它?br /> long(a)//a可以是指针地址,作用Q强制{换ؓ十进制数?br /> (void*)//ex:char str="abcde";cout<<str;str为首地址字符串的首地址输出。
18.输入W,提取W重载:<< >>
?54 155例题
19.盘文g的输入。头文g#include"fstream.h" //例题?56开?br /> 1.打开文gQ?br /> a. fstream outfile;
outfile.open("f1.txt",ios::out);//其中fstream为系l对文g专用操作c?br /> b. ofstream ostream("f1.txt");
ofstream ostrm; ostrm.open("f1.txt");//表示打开某个写文?br /> c. ifstream istrm("f2.txt");
ifstream istrm; istrm.open("f2.txt");//表示打开某个L?br /> -----------------------------------------------------------------------
方式名 ?| 用?br /> ----------------------------------------------------------------------
in | 以输入方式打开文g
-----------------------------------------------------------------------
out | 以输出方式打开文g
-----------------------------------------------------------------------
app | 以输加方式打开文g
-----------------------------------------------------------------------
ate | 文g打开Ӟ文g指针位于文g?br /> -----------------------------------------------------------------------
trunc | 如果文g存在Q将光度截断ؓӞq清除所有内容,如果文g不存在,则创建新文g
-----------------------------------------------------------------------
binarg | 以二q制方式打开文gQ缺省时为文本方?br /> -----------------------------------------------------------------------
nocreate |打开一个已有文Ӟ如该文g不存在,则打开p|
-----------------------------------------------------------------------
noreplace |如果文g存在Q除非设|?ios::ate或ios::app,否则打开p|
-----------------------------------------------------------------------
ios::in |ios::out |以读和写的方式打开文g
-----------------------------------------------------------------------
ios::out|ios::binary |以二q制方式打开文g
-----------------------------------------------------------------------
ios::in|ios::binary |以二q制方式打开文g
-----------------------------------------------------------------------
2. 关闭文g:
fstream outfile;
outfile.close();
3. 打开文gp|退出程序:用函数abort();退出,在头文g<stdlib.h"
4.判断文gl束函数.example: infile.eof()
5.getlineQchar*,sizeof(s));//d一串字W?br /> get()/put()//Ҏ件字W操作,例如outfile.get
6.随机讉K数据文gQ?
1)L?br /> istream &istream::seekg(中位置Q?/
istream &istream::seekg(偏移量,参照位置)//参照位置分ؓQcur=1/beg=0/end=2 input.seekg(-100,ios::cur);
streampos istream::tellg();//其中streampos定义为long型,它返回一个long型且gؓ当前指针L件开头的位置Q字节数Q?br /> 2)写指?br /> ostream &ostream::seekp(中的位|?
ostream &ostream::seekp(偏移量,参照位置Q?/参照位置同上
streampos ostream::tellp();
注意Q读函数中有get(),写函C有put(),操作L针用seekg(),而写指针用seekp();write()和read()中的W一个参数必Mؓ(char *),如果不是Q一定要强制转换
7. while(!cin);//表示输入有错?br /> cin.clear();//原型 void ios::clear(int=0);其用途是错误状态的标志字中错误标志位清除,重新判断输入?br /> cin.ignor(80,ch);//如果ch='\n',一般表C忽略一行,重新C一行去输入
istream &istream::ignore(int n=1,int t=EOF);//跌输入中指定数量的字W的函数Qt为终止符Q一般EOF相当?lt;ctrl+z>操作
istream &istream::pubback(char ch)//退回一个字W到输入的函数Q其中ch是指退回输入流的字W?br />20. 格式化输入和输出Q ?例题?167开?br /> A.讄的格式化标?br /> 1).控制格式的标志位
------------------------------------------------------------------------------
标志?| 值 ?| 含义 |输入/输出
------------------------------------------------------------------------------
skipws | 0x0001 | 跌输入中的I白W ?| i
------------------------------------------------------------------------------
left | 0x0002 | 输出数据左对齐 ?| o
------------------------------------------------------------------------------
rignt | 0x0004 | 输出数据叛_齐 ?| o
------------------------------------------------------------------------------
internal | 0x0008 | 数据的符号左寚wQ数据本w右寚wQ之间ؓ填充W ?| o
------------------------------------------------------------------------------
dec | 0x0010 | 转换基数为十q制形式 | i/o
------------------------------------------------------------------------------
oct | 0x0020 | 转换基数为八q制形式 | i/o
------------------------------------------------------------------------------
hex | 0x0040 | 转换基数为十六进制Ş式 ?| i/o
------------------------------------------------------------------------------
showbase | 0x0080 | 输出数据前有0/0x | o
------------------------------------------------------------------------------
showpoint | 0x0100 | 点数输出带有小数点 | o
------------------------------------------------------------------------------
uppercase | 0x0200 | 用大写字母输出十六进制数值 ?| o
------------------------------------------------------------------------------
showpos | 0x0400 | 正数前面有?”号 | o
------------------------------------------------------------------------------
scientfic | 0x0800 | 点数输出采用科学表C法 | o
------------------------------------------------------------------------------
fixed | 0x1000 | 使用定点数Ş式表CQҎ | o
------------------------------------------------------------------------------
unitbuf | 0x2000 | 完成输入操作后立卛_新流的缓冲区 | o
------------------------------------------------------------------------------
stdio | 0x4000 | 完成输入操作后刷新系l的stdout | o
------------------------------------------------------------------------------
2).使用成员函数讄标志字:
1.long flags() //该函数用来返回标志字
2.long flags(long) //该函C用参数更新标志字Q返回更新前的标志字
3.long setf(long setbits,long field)//field所指定的标志清Ӟsetbits?的位|?Q返回以前的标志?br /> 4.long setf(long) //讄参数所指定的那些标志的位,q回更新前的标志?br /> 5.long unsetf(long)//该函数用来清除参数所指定的那些标志位的位Q返回更新前的标志字
在ioscMQ定义了下面的表态类对象Q?br /> static const long basefield; //其gؓdec/oct/hex
static const long adjustfield //其gؓleft/right/internal
static const long floatfield //其gؓscientific/fixed
example: cin.setf(ios::dec,ios::basefield
B.格式输出函数:
1).讄输出数据所占宽度的函数
1.int width()//该函数返回当前输出数据的宽度
2.int width(int)//d数用来设|当前输出数据的宽度为参数|q返回更新前的宽度?br /> 2).填充当前宽度内的填充字符函数
1.char fill()//该函数用来返回当前所使用的填充字W?br /> 2.char fill(char)//该函数用来设|填充字Wؓ参数值所表示的字W,q返回更新前的填充字W?br /> 3).讄点数输出精度函?br /> 1.int precision()//该函数返回当前QҎ的有效数字的个数
2.int precision(int)//该函数设|QҎ输出时的有效数字个数Qƈq回更新前的倹{?br /> 注意:float型实数最多提?位有效数字,double型褛最多提?5位有效数字,long。。。提?9位有效数?br /> C.操作?Z化操作,提供了一pd操作子,操作子实际上是对?br /> --------------------------------------------------------------------
dec | 数值数据采用十q制表示 | i/o
--------------------------------------------------------------------
hex | 数值数据采用十六进制表C ?| i/o
--------------------------------------------------------------------
oct | 数值数据采用八q制表示 | i/o
--------------------------------------------------------------------
setbase(int)| 讄数据转换基数为n(n?,8,10,16)Q其?表示~省基数 | i/o
--------------------------------------------------------------------
ws | 提取I白W ?| i
--------------------------------------------------------------------
ends | 插入I白W ?| o
--------------------------------------------------------------------
flush | h与流相关联的~冲区 ?| o
--------------------------------------------------------------------
resetiosflags(long) | 清除参数所指定的标志位 | i/o
--------------------------------------------------------------------
setiosflags(long) | 讄参数所指定的标志位 | i/o
--------------------------------------------------------------------
setfill(int) | 讄填充字符 | o
--------------------------------------------------------------------
setsprecision(int) | 讄点数输出的有效数字个数 | o
--------------------------------------------------------------------
setw(int) | 讄输出数据的域宽 | o
--------------------------------------------------------------------
21. 字符串流:?70开?br /> c++提供了两个类:头文?include"strstrea.h"
1.ostrstream:其是从ostreamz来的,不同类型{换ؓ字符?q存攑ֈ数组?
ostrstream::ostrstream();//~省构造函?它用来徏立存储所插入的数据的数组对象;
ostrstream::ostrstream(char *s,int n,int mode=ios::out);//此构造函CS是字W指针或字符数组,N是用来指定这个数l最多能存放的字W个?mode参数l出式的方?~省为out方式,q可选用ate和app方式.
ostrstreamc还提供了如下的成员函数:
int ostrstream::pcount();//q回中已插入的字符个数;
char *ostrstream::str(); //q回标志字符串的数组的指针?
2.istrstream:其是从istreamz来的,文本项转换为变量所需要的内部格式.
istrstream::istrstream(char *s);//构造函CS是一个字W指针或字符数组,使用该串来初始化要创建的对?br /> istrstream::istrstream(char *s,int n);//此构造函数是使用串中前N个字W来构造串对象
22.异常处理
try{ }
throw 变量
catch(形式参数变量){ } //其中形数参数变量只能是一个,且类型不能像函数传递Ş参那栯行自动{换,必须完全扚w
注意Q?.当找不到指导配项Ӟq黑认扚wabort()一l止E序
2.异常处理的数据类型是公有基类Q抛掷异常的数据cd是派生类
3.异常处理的数据类型是指向公有基类的指针,抛掷异常的数据类型是指向zcȝ指针
catch(基类)总能够捕获throwQ派生类对象Q,所以catch(基类)块L攑֜catch(zc?块的后面Q以避免catch(zc?永远不能捕获异常