一、#include “filename.h”和#include <filename.h>的区别 @ojg`!,
5G'&9{oB
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 tC?Aso
1( ?CNW[
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 }^pQbFku
n-y^7'v
iijd$Tv
二、头文件的作用 -?aw^du
*{.&R9#7U'
加强安全检测 l|vWeBs
RUS7Z~5
通过头文件可能方便地调用库功能,而不必关心其实现方式 DO1 JPeIi
xMSNrOc
X40la_[.
三、* , &修饰符的位置 hINnb7o
Q.9Ph
~
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 jTd4 H)
S< EB&P
T6R7,Vt'v
四、if语句 EtR@sJ<
})zB".
不要将布尔变量与任何值进行比较,那会很容易出错的。 K=m9H=IX~T
q!hy;K`Jd
整形变量必须要有类型相同的值进行比较 MdVCD^B
84p[N8
浮点变量最好少比点,就算要比也要有值进行限制 $kkp*3{ot
|D;"D
指针变量要和NULL进行比较,不要和布尔型和整形比较 ZSF=
hy$MV3LP
8K@"B
五、const和#define的比较 B:3+',i1
l&6U|q`
const有数据类型,#define没有数据类型 `R=a@DQ
(>rS
_#^
个别编译器中const可以进行调试,#define不可以进行调试 wRXn9
t<!+b@l5
在类中定义常量有两种方式 b`h%W"|2L
]]J#7L#
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; h/ LR+XX!
iot.E%G
2、 用枚举代替const常量。 RwAbIXG{0
Yg=E@F
Z:_m}Ya|
六、C++函数中值的传递方式 r/CEYEJ&X
><;l:RGK|
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) GOYn\N;V2
)Lc<;=w'9
void fun(char c) //pass by value 85r)>aCMn
f
MY;
void fun(char *str) //pass by pointer ).0V%}>
F!OOrW]p0
void fun(char &str) //pass by reference a%7"_{s1
1<LC8?wt
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 %_B:EMPd
, @%C8Z
函数的类型不能省略,就算没有也要加个void -H1"OJ2aF
&YT_#M
?ID* /u|X
七、函数体中的指针或引用常量不能被返回 v!<PDw2'
hmK8jl<6
Char *func(void) j+_S$T8w
\6`v.B&v
{ .9T.3yQ
Z:#.;wA
char str[]=”Hello Word”; 6QN1+MwB
8- dRdQu]
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 YPF&U4CN
Bii6Z@kS
return str; sg3h i"Im
w1wXTt
} k~0#'I9
=4frP*H?
函数体内的指针变量并不会随着函数的消亡而自动释放 PHQ{-b?4t
$.oOG"u0]
!Oeq
G
八、一个内存拷贝函数的实现体 La`h$=#`
wzD\8_;6N
void *memcpy(void *pvTo,const void *pvFrom,size_t size) 2}^+]5
9 '2=
{ r_4TtP&UW
wl7 M fyU
assert((pvTo!=NULL)&&(pvFrom!=NULL)); !2GHJHxv]c
xK$}QZ)
byte *pbTo=(byte*)pvTo; //防止地址被改变 /a@ k S
Y3-]+y%l
byte *pbFrom=(byte*)pvFrom; q{a#HnZo"
e{,!|LhpQ
while (size-- >0) Z:I*y7V-
}Q/G
&F
pbTo++ = pbForm++; ^F>4~68d
~_ *H)|
return pvTo; 9aT L22U?
%lXbCE:[
} 7<^'DOs
n`P`yb\f$
T1l&B
九、内存的分配方式 ?V#Gx>\
&(gm4bTg
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 vGXWwQ.1Tp
KuA>"X
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 Kn']n91m
[!^cd%l
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 ows^W8-w
fCLcU@3W?
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 GA.BI"l
Y;8
>=0ye
V?=TVI*k
十、内存分配的注意事项 aw1P5aPmX
ir]Mn.(Y
用new或malloc分配内存时,必须要对此指针赋初值。 <# >Oy&E
/^J2B8y
用delete 或free释放内存后,必须要将指针指向NULL ?p(kh^ z
=KV@&Y^x4
不能修改指向常量的指针数据 ?~!tM}X0:3
WS5A Y @(~
-<6v:Z
十一、内容复制与比较 ]K7`-p~T
KL
"Y!PN:
//数组…… 1:_=g #WH
USprsaj
char a[]=”Hello Word!”; FS8S68
j5zFDh1(
char b[10]; Z)NrhJC
+i+tp8T+7
strcpy(b,a); k,T_e6(
dPHw3^J0j
if (strcmp(a,b)==0) <_t5:3HL
H-185]7
{} Yr+d1(
VQ2Fnb4
//指针…… ~]4kkm7Y
=Ci13< KQ
char a[]=”Hello Word!”; K<#-"Xe;
q?yMa9ZZky
char *p; z4g+2f7h-X
eO'xkm
p=new char[strlen(a)+1]; )`<6taKx@n
@YCv
strcpy(p,a); #'C/Gya
~^x-ym5
if (strcmp(p,a)==0) )U'yUUi
n? ]f@O R
{} !Vb,zQ
C,.-Q"juH
HM):"
十二、sizeof的问题 y<|)'(
>{QdMn
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 JPsSw
`
VwN!B:
char a[]=”Hello World!”
qtzFg#
qL3@PSN?|
char *p=a; C%]."R cMC
E`tQe5K
count<<sizeof(a)<<end; //12字节 N#UXP5C(
<Pio Q>~
count<<sizeof(p)<<endl; //4字节 t=i/xG: 5
qC..\{z
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 V}SyD(8~
iD<6t_8),
void fun(char a[1000]) Mb/L~gd"
v
J-LPTB
{ H UkerV
C3)|<E
count<<sizeof(a)<<endl; //输出4而不是1000 <5I1 DF[
gQ>2!Qc a-
} y
AOg\+
wyzOcx>M
61Bhm:O5W
十三、关于指针 zP&q7 t;>
[f/.!@sj
1、 指针创建时必须被初始化 um[!|g/
rrcwtLNbu
2、 指针在free 或delete后必须置为NULL {i>Jfl]G}
?q!FG(
3、 指针的长度都为4字节 ~.6|dw\p!
O3Uh+gKQ
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 +]c}rWm
_f3
WRyN0
char *p=new char[100]; x'qWM/
sAYV)w3u"
strcpy(p,”Hello World”); AK *N
HIGNRm
delete []p; //注意前面的[]号 m?;$;x~Dj
%2D17*eK
p=NULL; $O9Xx
c
0-w6
5、数组指针的内容不能超过数组指针的最大容易。 ?'sXgo.}
/.P9MSz0G
如: IqUp4}
`(DJs-xD
char *p=new char[5]; *QH[,F`I
HE;V zR
strcpy(p,”Hello World”); //报错 目标容易不够大 >zmzK{A=
/K|:9Q$K6
delete []p; //注意前面的[]号 O!^; mhy"
%LQ/q3?_
p=NULL; CCqT tp
"-
eZZEl(
xo Gb
十四、关于malloc/free 和new /delete -eml
V"#Jk!k9k
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 9&K/GaG
P^[/Qi}j
l 注意:malloc/free是库函数,new/delete是运算符 r5 yO5W
i2PZ'.sL
l malloc/free不能执行构造函数与析构函数,而new/delete可以 z(H?VfJo
[U.v:tR
l new/delete不能在C上运行,所以malloc/free不能被淘汰 *eUc.MX6x
7>n"}8i
l 两者都必须要成对使用 tZA:
0@pu@ DP~
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 Ld(NhB'7
|RhM| i
"8(U\KaX
十五、C++的特性 #$'FSy#
Yc`<S
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 >85zQ
1aL
'RTtE
重载和内联:即可用于全局函数,也可用于类的成员函数; ^%#grX#
|J3NR`-R
Const和Virtual:只可用于类的成员函数; 'jvpNn
q`Q}yE>9
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 "&QH6B1U6H
5~r2sCDPk
覆盖是指派生类函数覆盖基类函数 p=gX!4,9<
P`"mM?u
函数名相同; =|SdVv
s-?fUqA
参数相同; .y): Rh^
n%$ &=-Fk
基类函数必须有Virtual关键字; 'M/([|@
]b}B2F'n
不同的范围(派生类和基类)。 '*R%^RK
^M[P-#X_
隐藏是指派生类屏蔽了基类的同名函数相同 *H2]H@QHN
!buz<h
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 ~V+l_:
kso*} uh0
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 ~<ri97)
%Q4i%:Qi
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 ,rO[mNk9@
KCtX$XGL
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 rFu ez$
m#H_*L0
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 <avQR9'&
4v.d-^
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: l(:kfR~AC
]QrR1Rg
将void Func(A a) 改为void Func(const A &a)。 Qv{,wytyO
|wp,f%WK
而void func(int a)就没必要改成void func(const int &a); Lj
8<'"U#
KIus/S5
RC
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 OJ3UE(,I=
EHI 'xt
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 E*CcV;
qX6D1X1_
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; .C!vr@@]
qL
5>o>J
(Hp' B))2
十六、extern“C”有什么作用? yyP-=Lhmo=
\b8\Ug~t
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 j43$]'-
%SA!p;
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 ai-n z-;
mTf<
1>pe&n/
十七、构造函数与析构函数 1ThqqB
pJ^NA2
派生类的构造函数应在初始化表里调用基类的构造函数; %1}6q`:w
b2)\
MNH
派生类和基类的析构函数应加Virtual关键字。 Qc"'8kt
q,l)I+
不要小看构造函数和析构函数,其实编起来还是不容易。 ejePDgi_[
@WOM#Kc
#include <iostream.h> ")UwkF
@,OT/egF4:
class Base b{cU<;G)y.
w1^QD^KnH
{ jna;0)
rT6?!$"%.
public: q mQfLz7&x
WxUxc75
virtual ~Base() { cout<< "~Base" << endl ; } I.jZ
wW!r
S2^>6/[xM
}; v#oi0-9o[
B6M+mx"G
class Derived : public Base SNY (*
IOl+t,0x&
{ 5<+K?uhm
3Qn!y\#
public: gPXa>C
7{M>!}
rY
virtual ~Derived() { cout<< "~Derived" << endl ; } :0~QRc-u
u=NG6G
}; *dsX#Iz
&0
\
ci9o
void main(void) r@}bDkx
E`;;&V q-
{ v/QUjXBr
N|Cs=-+
Base * pB = new Derived; // upcast ?vtX"Fdz
N$I03m
delete pB; ;sOsT?)7$
@!%n$>p/V
} .zj0Jy8N
ql{_%x?
输出结果为: `dkV_ O0
v/Pw9j!r;m
~Derived z~oDWANP
|\9TvN^$`
~Base *VeW?mY,P
^))RM_ic
如果析构函数不为虚,那么输出结果为 J%rP$O$
UE0$ o?
~Base hf<J
\
!u|Tu4G^
[0;buVU.
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 1T|$BK@)
?A*Kg;IU
仿止该头文件被重复引用