一、#include “filename.h”和#include <filename.h>的区别 8+f{ /
}Z/[ "
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 0sMNp
hD>]\u
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 0Cg}yy Oz
h 8%(,$*
&9+]{jXF
二、头文件的作用 ZZs@P#]
us5<18M5
加强安全检测 Fe[)-_%G
h6CAd-\x\
通过头文件可能方便地调用库功能,而不必关心其实现方式 %`EyG
@d&JtA
TS_5R>R3
三、* , &修饰符的位置 f: 9bq}vH
`w6*(t:T
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 aM7e?.rU
cyMvjzzRN
u1}/SlCp
四、if语句 K N Y
)_&P:;N
不要将布尔变量与任何值进行比较,那会很容易出错的。 ndmsXls
bIWSNNV0F
整形变量必须要有类型相同的值进行比较 JpRn)e'Z
4Wd
H!z
浮点变量最好少比点,就算要比也要有值进行限制 ]/9@^D}&
x/pX?k
指针变量要和NULL进行比较,不要和布尔型和整形比较 ybC0Ee@
Aaw]=8 OI
~hZr1hT6L
五、const和#define的比较 exZgk2[0
A_!N,<-
const有数据类型,#define没有数据类型 H9\,;kM)
"u.'JE;j
个别编译器中const可以进行调试,#define不可以进行调试 D_N0j{E
}>5R9
在类中定义常量有两种方式 HUFm@?
=Lh8#>T\h
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; {e+}jZ[L
@*16agGg
2、 用枚举代替const常量。 rNK<p3=7)
}PXtwp13&u
bA-/"'Vp9
六、C++函数中值的传递方式 KqL+R$??"(
S.zY0
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) @tX8M[.eA
U!GfDt
void fun(char c) //pass by value 3v91 yMx
.rwa=IW
void fun(char *str) //pass by pointer o5E5s9n
34
'[O
void fun(char &str) //pass by reference z"D0Th`S6
#ZC9=
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 * lJkk
~} 02q5H
函数的类型不能省略,就算没有也要加个void !C& ^%a
`t>A~.f
!gm@QO cF
七、函数体中的指针或引用常量不能被返回 h]]B@~
"C.cU
Char *func(void) )Z*nm<=
N;HG@B!m
{ -kP$S qR~
y]okOEV0
char str[]=”Hello Word”; S l`F`
1)H;}%[
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 FvJkb!5*e_
}*P?KV (
return str; rw$ =!iyO
N}ugI`:
} NY
GWA4L
m;JB=MZ=m
函数体内的指针变量并不会随着函数的消亡而自动释放 7<*,O&![|
JA$RY
S-[S?&c`
八、一个内存拷贝函数的实现体 lt("yqBu
g5;Ig
void *memcpy(void *pvTo,const void *pvFrom,size_t size) kxLWk%V
`qV*R
2
{ FN<Sagj
l`Ae&nc6
assert((pvTo!=NULL)&&(pvFrom!=NULL)); 8Sk$o.Gy
8
KRo<
byte *pbTo=(byte*)pvTo; //防止地址被改变 Zg4kO;r08
$!vK#8-&{
byte *pbFrom=(byte*)pvFrom; z?Cez*.h>
;LC?3.
while (size-- >0) (@Kc(>(: Y
p=[SDk`
pbTo++ = pbForm++; m@W>ku
4 'DEdx,&f
return pvTo; gle<{
`
48,uO!
} 3ESrd"W=
/?1^&a
d
f
j;e%H
九、内存的分配方式 ]m :Y|,:6
n= q7*<l
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 d/[kky}
:rU,7`sE/
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 6@VgLa,
z~th{4#E;
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 e!ql8wbp
LvCX(yjZ*
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 v"l8[::
&bigLe
IQWoK"B
十、内存分配的注意事项 K8W99:v
LMNmG]#!
用new或malloc分配内存时,必须要对此指针赋初值。 PVSz%"
t[ZGY,8
用delete 或free释放内存后,必须要将指针指向NULL y" |gC!V}
C[,&Y&`j
不能修改指向常量的指针数据 K@vU_x0Sl
9/=+2SZ
-'
=?Hs.
十一、内容复制与比较 _`.Q7
!tSh9L;<O
//数组…… d+nxvh?I8
c=D~hz N
char a[]=”Hello Word!”; L+CPT
@V Sr'?7-
char b[10]; :_h#A}8Xd
Ek60[a
strcpy(b,a); q<K/q"0-l
4+Jf!ovS=
if (strcmp(a,b)==0) 1/v#Z#3[
V0G[f}tm'
{} 3pe1"maP
p/HGI)'
//指针…… 3U'l'H,
iikMz|:7U
char a[]=”Hello Word!”; 30O7u3Zrb
*6G@8TIh
char *p; "|BSGV!8
Hb[P|pPT
p=new char[strlen(a)+1]; T_d)1m fl
iZ4"@G:,
strcpy(p,a); Q)=2%X
x2f=o|]D'
if (strcmp(p,a)==0) ,'n`]@0?\
xX@9wNYD
{} FQ0PXYh
MS]Q\g}U
6(>,qt,9S
十二、sizeof的问题 Fd<eh(g9P
Bh&dV%'
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 a+j"8tHu$
O"#/>hmv-
char a[]=”Hello World!” kJ?AAPC
<O.|pJus
char *p=a; +$F,!rV-s
S~>R}=
count<<sizeof(a)<<end; //12字节 >qPP_^]
j^/=.cD|
count<<sizeof(p)<<endl; //4字节 $EL:Jx2<
!;Ke# E_d
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 hrGX65>
%/d1x
void fun(char a[1000]) {B4.G8%Z
^v+p@k
{ czsnPmNEI
r5y*SoD!
count<<sizeof(a)<<endl; //输出4而不是1000 P26"z))~d
tO?-@Qf/9<
} HQnc`2
G=LK
irj(
lh6N3d
十三、关于指针 q8H nPXV
d5`D[,]d
1、 指针创建时必须被初始化 X|aD>CT
S|fb'
2、 指针在free 或delete后必须置为NULL biS{.
HBZ6 Pj
3、 指针的长度都为4字节 dkeMiLm
Ro;I%j
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 mW~*GD~r
s~ou$!|
char *p=new char[100]; 6
$`l
.@ZrmO
o]]
strcpy(p,”Hello World”); 5vLA)Al3
Mcq!QaO}&
delete []p; //注意前面的[]号 < FY%QB)h
[,{Nu EI
p=NULL; ";/ogFi
)i_:[ l6
5、数组指针的内容不能超过数组指针的最大容易。 D G|v'#
IyM:9=}5
如: zZP/C
5#y_EpL"
char *p=new char[5]; 13*S<\
D]5j?X'
strcpy(p,”Hello World”); //报错 目标容易不够大 aj/+#G2
d%RH]j4
delete []p; //注意前面的[]号 9aX!<Z
#$]8WSl
p=NULL; ou{V/?rb
(g&@E(@]?
T^{=cx9x9
十四、关于malloc/free 和new /delete dK;ebg9|
LIKQQ
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 s< Fp17
,LC(Ax'.F
l 注意:malloc/free是库函数,new/delete是运算符 @2On`~C`
`Y^l.%AZZ
l malloc/free不能执行构造函数与析构函数,而new/delete可以 SbQ:vAE*ho
V(g5Gn?
l new/delete不能在C上运行,所以malloc/free不能被淘汰 `5"3Cj"M
drvrj~o:
l 两者都必须要成对使用 m4yWhUi(o
Yh Ow0 x
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 qe22 kE#
suYbD!`(
'Hs*
十五、C++的特性 4?bvJJuf)
*_P'> V#p
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 J#q^CWN3R
,gM:s}l!dJ
重载和内联:即可用于全局函数,也可用于类的成员函数; Az-!X!O*f
,6o tm
Const和Virtual:只可用于类的成员函数; @sW!g;\T
PIdGis5G
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 <;uM/vSi
?b"'w
覆盖是指派生类函数覆盖基类函数 A-J#$B
OJh MM-
函数名相同; )."dqq^ q
}Oqt=Wm
参数相同; kB%.i%9\\
}8s&~fH
基类函数必须有Virtual关键字; _g-0"a{-
]h=5d09z
不同的范围(派生类和基类)。 @=
=)
n&DBMU
隐藏是指派生类屏蔽了基类的同名函数相同 EXwU{Hl
owI:Qs_/4
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 |68u4z K
z@ `u$D$n
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 EWY'E;0@5
ZE=
Yn~XM
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 *xITMi
Xbrc_V\_
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 WJ LqH<
}%<_>b\
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 9XhH*tBn7(
M%RH4%NZ0
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: &pR 8sySu
_Vf>>tuW
将void Func(A a) 改为void Func(const A &a)。 #?,"/Btq
8EX?/33$
而void func(int a)就没必要改成void func(const int &a); 3g5r}Ug
0Wc_m;
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 2m} bddS
e,Y<$kPV
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 EziGkbpd@
I Gi9YpI&K
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; 1 o_6WU
g \ou+M#
kbJ4CF}H
十六、extern“C”有什么作用? B6KG\,'|
M*C1QQf\N
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 }Z t#OA
$
z-:>[Sn
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 Hs_7oy|P
$DtUTh3)
z@V9%xF-3
十七、构造函数与析构函数 t* p%!xsH
/Ahh6=qQY
派生类的构造函数应在初始化表里调用基类的构造函数; #&fu"W+D96
nR w f;K
派生类和基类的析构函数应加Virtual关键字。 Aa]3jev
Q1x15pVku/
不要小看构造函数和析构函数,其实编起来还是不容易。 D;jbZ9
s:(z;cj/
#include <iostream.h> 'KT(;Vof
2;J\Z=7
class Base 6V}xgfB
EJQT\c
{ SJlE!MK
+_u~Np
public: [hk/Rp7{
%Pj}
virtual ~Base() { cout<< "~Base" << endl ; } ~*UY[!+4^=
7,8TMd1`M
}; 8?x:PkK
pYu6[
class Derived : public Base tmM; Z(9t
Y> ATL
{ 3-)}.8F
uPxjW"M+
public: g5u4|+70
TIR Is1
virtual ~Derived() { cout<< "~Derived" << endl ; } (<-m|H};
ll- KK`Ka
}; 0
0|!g"E>$
B7YE+
void main(void) &
9
c^9<F
065 =I+Vo
{ x5Fo?E
zA:q/i
Base * pB = new Derived; // upcast jUgx
;=
A wk1d
delete pB; ;sq xFF@
zK{}
} ?r5a*
r.6?|
输出结果为: ,?Zy4-
='_3qn.
~Derived i\gt
@
79-50}A
~Base x;-D}#
}UQ,B
如果析构函数不为虚,那么输出结果为 @LDs$"f9=
j]]5&u/l
~Base qDhZC*"9#D
X8?@Y@
IiE^HgM
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 @$
lX%p>
g jzWW0C
仿止该头文件被重复引用