一、#include “filename.h”和#include <filename.h>的区别 Lv)1
)'v0
y\:Ma7V
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件
b`GKGqb J
X #$l7I9H
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 Qip@L WvT
J9J/3O
Q=
x lsAct:
二、头文件的作用 ExFz@6@
"d0D8B7HI@
加强安全检测 |WT]s B0Eq
c:B` <
通过头文件可能方便地调用库功能,而不必关心其实现方式 I,Jb_)H&t
r0pwKRE~t
On[yL$?
三、* , &修饰符的位置 zW`a]n.
SC3_S.
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 d<m.5ECC}
SUvrOl
yKz%-6cpSl
四、if语句 g^jTdrW/s
vr6YE;Rs
不要将布尔变量与任何值进行比较,那会很容易出错的。 /z}b1m+
=?\%E[j
整形变量必须要有类型相同的值进行比较 `Hu2a]e9
u2[L^]|
浮点变量最好少比点,就算要比也要有值进行限制 d+
[2Sm(7
ZC^NhgX
指针变量要和NULL进行比较,不要和布尔型和整形比较 uA t{WDHm
_ib
@<%
d*U<Ww^q
五、const和#define的比较 Ue>{n{H"y
#D ]CuSi
const有数据类型,#define没有数据类型 6y^GMlsI
{lppv(U
个别编译器中const可以进行调试,#define不可以进行调试 U+["b-c
>4+KEK
在类中定义常量有两种方式 h$6~3^g:P
lO 0}
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; Jy('tfAHp
e:rbyzf#
2、 用枚举代替const常量。 ;Z`R!
L7.SH#m
P%!=Rj^ 2m
六、C++函数中值的传递方式 Cm"S=gV
LEX @hkh
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) f'M([gn^_
`UqX`MFz
void fun(char c) //pass by value i;juwc^n}
EiZa,}A
void fun(char *str) //pass by pointer $++O@C5
L
gy^^.
void fun(char &str) //pass by reference y(^\]-fE
.t&G^i'n
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 M7&G9SGZ
P>`|.@
函数的类型不能省略,就算没有也要加个void nC!L<OMr
5/CF_v
&$l#0?Kc^
七、函数体中的指针或引用常量不能被返回 @Q;s[Kg{!
mwI7[I2q
Char *func(void) @tJic|)x
O,NVhU7,
{ 8f65;lyN
OF-VVIS
char str[]=”Hello Word”; {:Kr't<XzF
{9^p3Q+:P
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 q)AX*T+
3Y&4yIx
return str; =([4pG
dt"&
} T{yJL<
VC%.u.< F
函数体内的指针变量并不会随着函数的消亡而自动释放 $3%+N|L
o-;/x)
+F2X2e)g"
八、一个内存拷贝函数的实现体 ]M'~uTf
6}|h
void *memcpy(void *pvTo,const void *pvFrom,size_t size) j"VDqDDz
"{Y6.)x
{ S.<4t*,
wTG(U3{3K
assert((pvTo!=NULL)&&(pvFrom!=NULL)); Y4_xV&
/?Mr2!3N
byte *pbTo=(byte*)pvTo; //防止地址被改变 YhC|hDC
Z aS29}
byte *pbFrom=(byte*)pvFrom; KCH`=lX
9b@yDq3hQ
while (size-- >0) tE-g]y3
M* {5> !\
pbTo++ = pbForm++; Z/|=@gpw
:3b02}b7
return pvTo; W,_2JqQp
<td]k%*+
} h ^s8LE3
JO90TP
$
k1s5cg=n(
九、内存的分配方式 >Q?8tGfB
@7V~CNB+
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 >VX'`5r>uw
n+i=Ff
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 KD H<T4#x
vbZ!NO!H
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 *v?kp>O
c&
bms)Jwa
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 5}Xi`'g,
^Xu4N"@
;Zr7NKs
十、内存分配的注意事项 (Nv-wU
)?c,&
用new或malloc分配内存时,必须要对此指针赋初值。 5O
Y5b8
49c-`[d
L
用delete 或free释放内存后,必须要将指针指向NULL Uqy/~n-v<
e0otr_)3F
不能修改指向常量的指针数据 %~PT7"4
}&==;7,O
\j3dB
tc
十一、内容复制与比较 ItZYOt|Hn
ju.pQ=PSX
//数组…… &ODo7@v`1
bSz7?NAp
char a[]=”Hello Word!”; `u PLyS.
6]kBG?m0
char b[10]; m]vV.pwv
fFWi
3.
strcpy(b,a); Hrph>v
#.$y
if (strcmp(a,b)==0) R^P>yk8
RVLVY:h|F
{} 4RYH^9;>K
@qj]`}Gx'
//指针…… g|7o1{
CyW|k
Dz
char a[]=”Hello Word!”; cDE5/!
!\9^|Ef?
char *p; SW'eTG
Au}l^&,zN
p=new char[strlen(a)+1]; XoL DqN!
I~@8SSO,vH
strcpy(p,a); %'Q2c'r
uoeZb=<
if (strcmp(p,a)==0) VuH ->
<JU3sXl
{} "k{so',7z
=WBfaxL}
TsG x2[
十二、sizeof的问题 Q~VM.G
/kg#i&bP~
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 Gn_DIFa
0 yq
char a[]=”Hello World!” vv{+p(~**O
fwV2b<[
char *p=a; w D r/T3
"42/P4:
count<<sizeof(a)<<end; //12字节 T<?kH
FO:L+&hr?>
count<<sizeof(p)<<endl; //4字节 +F2OPIanT~
.g\Oj0Cbxh
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 }(|gC,
LdN[N^n[H
void fun(char a[1000]) k0K$OX*:e
DL1nD5
{ !4'F z[RK
!2l2;?jM
count<<sizeof(a)<<endl; //输出4而不是1000 T,1qR:58
$sE=[j'v
} H"6x/&s.=k
Ve&_NVPrd
k%i.B
十三、关于指针 wlaPE8Gc
"QxULiw
1、 指针创建时必须被初始化 r]Wt! oHm5
n$r`s`}
2、 指针在free 或delete后必须置为NULL #S'uqP!
>RAg63!`
3、 指针的长度都为4字节 4n7Kz_!SVf
,_Bn{T=U
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 NR1M W^R
tZz%x?3G
char *p=new char[100]; ]rH[+t-
J&,hC%]
strcpy(p,”Hello World”); %oTBh* K'o
fe98Y-e
delete []p; //注意前面的[]号 h\w;SDwOk
,)#rD9ZnC
p=NULL; )`f-qTe
~ILv*v@m
5、数组指针的内容不能超过数组指针的最大容易。 &{a!)I>
6AG]7d<
如: UGy3B)
(EY@{'.&
char *p=new char[5]; 3?]81v/
0#!}s&j/
strcpy(p,”Hello World”); //报错 目标容易不够大
Y6VJr+Ap(
x]x 3iFD
delete []p; //注意前面的[]号 L'?aoRj
GyN|beou
p=NULL; jgIG";:Q
m{ !$_z8:
zdRVAcrwQ
十四、关于malloc/free 和new /delete tJrGRlB>
4=Ru{ewRV
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 : #CWiq("%
"5~?`5Ff
l 注意:malloc/free是库函数,new/delete是运算符 \2 N;VE
%bN{FKNN
l malloc/free不能执行构造函数与析构函数,而new/delete可以 LkS tU)
|<,qnf| -
l new/delete不能在C上运行,所以malloc/free不能被淘汰 vu\W5M
=CK% Zo
l 两者都必须要成对使用 Jcze.t
7cGOJA5&
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 [,AFtg[
&kmaKc
t8EI"|
十五、C++的特性 9=MNuV9/s
}_zN%Tf~
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 )-&@8`
t,|Apl]
重载和内联:即可用于全局函数,也可用于类的成员函数; O@a OKk
&'W7-Z\j-
Const和Virtual:只可用于类的成员函数; ?j.a>{
'`k7l7I[@
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 |f fHOef
92<+ug =
覆盖是指派生类函数覆盖基类函数 = +MF@ 4
-^CW}IM{ I
函数名相同; M1-tRF
sPvs}}Z]P
参数相同; mB_?N $K
pxTtV g.
基类函数必须有Virtual关键字; ;QXg*GNAv$
<$z[pw<
不同的范围(派生类和基类)。 Twa(RjB<
Q^2dZXk~
隐藏是指派生类屏蔽了基类的同名函数相同 '2lzMc>wvP
0<!9D):Bb
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 q&-mbWBj
P ljPhAce
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 #RR;?`,L}
t"GnmeH
i
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 ,W)DQwAg
MSS[-}
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 ?YL JXq
B.5+!z&7
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 e3SnC:OWf
Az:~|P
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如:
%lnkD5
yM@sGz6c!
将void Func(A a) 改为void Func(const A &a)。 { im?tZ,
V_J0I*Qa4
而void func(int a)就没必要改成void func(const int &a); &!X<F,
HAK,z0/
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 ^t4^gcoZ4Z
7wx=#
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 '=E;^'Rl
u.X]K:Yow
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; [E
a{);
g,JfT^
.4%z$(+6
十六、extern“C”有什么作用? h6D4CT
)mm0PJF~q
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 yor'"6)i
<jV,VKL#
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 QNx]8r
]Wkgpfd56
RQ8d1US
十七、构造函数与析构函数 Nq`;\E.M
j_so s%-
派生类的构造函数应在初始化表里调用基类的构造函数; 62R";# K
,:(s=JN+
派生类和基类的析构函数应加Virtual关键字。 N=1ue`i
ZEI)U,
I.
不要小看构造函数和析构函数,其实编起来还是不容易。 ~@c<5 -`{
s oY\6mHio
#include <iostream.h> '/8/M{`s
<WIIurp
class Base b:F;6X0~Hl
PEvY3F}_rh
{ [oU\l+t
f5 bq)Pm&
public: vmAnBY
p\=T#lb
virtual ~Base() { cout<< "~Base" << endl ; } uG7]s]Wdz;
$f3 IO#N
}; <)T| HKx
?3BcjD0
class Derived : public Base o@L0ET
?P0b/g
{ #b;?:.m\=
zz
U,0
L
public: gP
QOv
$}WT"K
virtual ~Derived() { cout<< "~Derived" << endl ; } T)I)r239h
gf8o~vKX$G
}; %evb.h)
aNu.4c/5
void main(void) I^k&v V
@)h>vg
{ Yg.[R]
UC
HZ'rM5Kq
Base * pB = new Derived; // upcast F@Sk=l(
z<5 5[~3
delete pB; F&wAre<
phu,&DS!
} 8HKv_vl
!rRBy3&
输出结果为: z9S
(<