一、#include “filename.h”和#include <filename.h>的区别 yBLUNIr
kW6%32
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 {dPgf
5)zn :$cz
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 JO@Bf
OMihXt[
|m,VTViv;i
二、头文件的作用 R*1kR|*_)
d~ng6pA
加强安全检测 *.f2VQ~H
y?30_#[dN
通过头文件可能方便地调用库功能,而不必关心其实现方式 dMl+ko
%K 4
(}!C4S3#
三、* , &修饰符的位置 |'HLz=5\
Jx-wO/
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 {bF1\S]2
77gysd\(
y[0`hSQ)~
四、if语句 =Pe><k
`GQ{*_-
不要将布尔变量与任何值进行比较,那会很容易出错的。 7z~Ghz
yno(' 1B@
整形变量必须要有类型相同的值进行比较 0?bA$y
E\2Ml@J
浮点变量最好少比点,就算要比也要有值进行限制 4cCF\&yU
N:+
taz-
指针变量要和NULL进行比较,不要和布尔型和整形比较 >tRHNB_
['X[qn
Yq'4e[i
五、const和#define的比较 1H4fJ3-
Edt}",s7
const有数据类型,#define没有数据类型 #]KgUc5B
N=,j}FY
个别编译器中const可以进行调试,#define不可以进行调试 &m{'nRU}c
Lue|Plm[y
在类中定义常量有两种方式 "/%89 HMD
"HQF.#\#
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; k{Lv37H
vahoSc;sw
2、 用枚举代替const常量。 2P~)I)3V
2z2`
QocQowz
六、C++函数中值的传递方式 XQ;I,\m
cqL(^R.
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) |'hLa
Px4/O~bLk
void fun(char c) //pass by value ]EL\)xCr
\aSz2lxEHn
void fun(char *str) //pass by pointer sk X]8
o)]FtL:mm
void fun(char &str) //pass by reference .gD km^
`^8*<+
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 9&jPp4qG
12gw#J/)9h
函数的类型不能省略,就算没有也要加个void emWGIo
.H;B=nd*
h`?k.{})M
七、函数体中的指针或引用常量不能被返回 Cd~LsdKE5
cC6z,0`3
Char *func(void) {\We72!
yq*JdTF
{ /t{=8v~
sc xLB;
char str[]=”Hello Word”; ZgF/;8!~V-
;QPy:x3
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 vgk9b!Xd
,ep9V,+|
return str; /2w@K_Px6
BED@?:U# h
} BJIQ
zn3
>UN vkQ:
函数体内的指针变量并不会随着函数的消亡而自动释放 (Jpm
K O
uC[d% v`
-3k;u
八、一个内存拷贝函数的实现体 qy9i9$8
#JS`e_3Rr
void *memcpy(void *pvTo,const void *pvFrom,size_t size) ADBpX>
cHEz{'1m
{ 5&(3A|P2
C1ZyB"{
assert((pvTo!=NULL)&&(pvFrom!=NULL)); {Q<0\`A
0BXs&i-TP5
byte *pbTo=(byte*)pvTo; //防止地址被改变 y< ud('D
<(uTst
byte *pbFrom=(byte*)pvFrom; }} # be
5G oK"F0i
while (size-- >0) u\w 2S4c
*[
#*n n
pbTo++ = pbForm++; `vX4!@Tw
j@SYXKL~
return pvTo; <i7agEdZD
D"`[6EN[
} jMqx
oVEAlBm^v
2YluJ:LN
九、内存的分配方式 z+Z%H#9e
#{~7G%GPY5
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 8 >dq=0:
bN!u}DnN
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 ?q6Z's[
S|) J{~QH
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 6d};|#}
} bCK
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 NkoofhZ
;,v.(Z ic
:r-.r"[m-
十、内存分配的注意事项 *LEu=3lp%>
*@~`d*d
用new或malloc分配内存时,必须要对此指针赋初值。 u YabJqV
YPG,9iZ&f
用delete 或free释放内存后,必须要将指针指向NULL ]*a@*0=
gu!](yEgl
不能修改指向常量的指针数据 q>P[n z%
$)l2G;&
j7,13,t1-
十一、内容复制与比较 v10mDr
MN\i-vAL8
//数组…… 1O23"o5=
+R9%~Z.=
char a[]=”Hello Word!”; q _19&;&
C)U #T)
char b[10]; ,}n=Z
t(wZiK}
strcpy(b,a); JR!Q,7S2!N
7t`E@dm
if (strcmp(a,b)==0) r)c+".0d^
^uM_b
{} j6RJC
g(KK9Unu
//指针…… L!?v BL
avmcGyL
char a[]=”Hello Word!”; bG"6pU
%7iUlO}}V
char *p; D8gQRQ
=A$Lgk>|
p=new char[strlen(a)+1]; "IOC[ #&G
-e &$,R>;
strcpy(p,a); sN"p5p
=kwb`
Z/a
if (strcmp(p,a)==0) K<RmaXZ
zoR,RBU6
{} KSF5)CZ5
qK{|Q
\)uy"+ Z`
十二、sizeof的问题 *iPs4Es-
+[>yO _}
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 7ytm.lU
@gs26jX~2}
char a[]=”Hello World!” N9`y,Cos0
|*lH9lWJ
char *p=a; yW%&_s0
:yd=No@
count<<sizeof(a)<<end; //12字节 <+ -V5O^
V#p G; ,
count<<sizeof(p)<<endl; //4字节 2qt=jz\s
8W(<q|t
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 +I^+k "
l
:f9Ih
void fun(char a[1000]) }K#iCby4
QWU5-p9e8
{ #k"1wSx16
L+v8E/W
count<<sizeof(a)<<endl; //输出4而不是1000 /E=h{|
U;x99Go:
} {KF 7j63
3N(8|wh
113Z@F
十三、关于指针 h<PYE]?l
[{hL F9yPx
1、 指针创建时必须被初始化 jrDz7AfA
DR.3
J`?K
2、 指针在free 或delete后必须置为NULL [V!^\g\6
pkrl@jv >
3、 指针的长度都为4字节 @t{{Q1
WyKUvVi
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 ucIVVT(u
O+CF/ipX/
char *p=new char[100]; v*vub#wP
YHwVj?6W
strcpy(p,”Hello World”); fS;m+ D!j@
B`'}&6jr.
delete []p; //注意前面的[]号 ZwY`x')
X m_Ub>N5
p=NULL; '=@-aVp
20SF<V
5、数组指针的内容不能超过数组指针的最大容易。 @j)f(Zlu#
-y7l?N5F>
如: \?5[RR
qiwQUm{
char *p=new char[5]; HQ-N!pf9
[A.eVuV;+
strcpy(p,”Hello World”); //报错 目标容易不够大 $S"zxEJJ Y
LN,$P
delete []p; //注意前面的[]号 tA;ZW2$#
;&7qw69k
p=NULL; gn;nS{A
$w2[5|^S
3!ajvSOI9j
十四、关于malloc/free 和new /delete <E(-QJ
b_)QBE9
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 O(c4iWm
<9MQ
l 注意:malloc/free是库函数,new/delete是运算符 B<|q{D$N/
U3VsMV*Y
l malloc/free不能执行构造函数与析构函数,而new/delete可以 rsq'60
52q!zx E
l new/delete不能在C上运行,所以malloc/free不能被淘汰 W+-f `
Ri%Of:zZ
l 两者都必须要成对使用 s]V{}bY`
5u=U--
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 U`vt/#j
1
QVA!z##
nu1w:
十五、C++的特性 /fcwz5~
vp9E}ga
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 @%5F^Vbd
Qg8eq_m(
重载和内联:即可用于全局函数,也可用于类的成员函数; `(w kqa
`b,g2XA
Const和Virtual:只可用于类的成员函数; k?@W/}Iv9
m SvTnd8
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 ?),K=E+=U
)I0g&e^Tzy
覆盖是指派生类函数覆盖基类函数
_ jM6ej<
BfO}4
函数名相同; #7E&16Fk
4QN6BZJ5
参数相同; Ni;{\"Gt
F\$}8,9
基类函数必须有Virtual关键字; jind!@}!
J jL0/&
不同的范围(派生类和基类)。 k?_$h<Y
(l,YI"TzT
隐藏是指派生类屏蔽了基类的同名函数相同 l=.InSuLT
v+,
w{~7RH
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 U1@P/
@zpHemdB
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 jl|X$w
.~/;v~bL
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 [+5SEr}
sRI=TE]s
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 JZ*?1S>
Ffqn|}gb
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 sZ(Q4)r
/:];2P6#X
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: gj(l&F *@
-
&LZle&M
将void Func(A a) 改为void Func(const A &a)。 r:b.>5CS)
`[R:L.H1
而void func(int a)就没必要改成void func(const int &a); W!Os ci
Op)R3qt{
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 XwqfWd_
zj0pP{y
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 N =}Z#
nT6iS}h
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; &ppZRdq]
-)c"cgx.
ZtZV:re=
十六、extern“C”有什么作用? c;fyUi
MkIO0&0O
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 3xR#,22:}
'48|f`8$
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 jF2GHyB
Y@xeyMzE
e(5Px!B
十七、构造函数与析构函数 0hr)tYW,G
WN?`Od:y
派生类的构造函数应在初始化表里调用基类的构造函数; -|UX}t*
9!<3qx/
派生类和基类的析构函数应加Virtual关键字。 rY+1s^F
l3
Bc
g
不要小看构造函数和析构函数,其实编起来还是不容易。 N>#P
1!eP
Tp.iRFFkP
#include <iostream.h> n/|`Dz.
QRix_2+
class Base #8HXR3L5=!
gG?*Fi
{ Or~6t}f
:l[Q
public: U-N/Z\QD
b-gVRf#F
virtual ~Base() { cout<< "~Base" << endl ; } Ol^EQLO
9O_N
iu0
}; QE6-(/
--hnv/AjI
class Derived : public Base ?a_q!,8:
DFH6.0UW
{ (9lx5
WM7/|.HQ
public: 9E*K44L/V
<W{0@?y
virtual ~Derived() { cout<< "~Derived" << endl ; } "+Yn;9
YR`rg;n#
}; F#R\Ot,hv
K8we*
void main(void) soCHwiE
=5#Jsn?U
{ ~&jCz4M
-v2q:x'G#
Base * pB = new Derived; // upcast ZOsn,nF
ml/O
delete pB; J<O_N~$$*
DN_C7\CoA
} SuuS!U+i>
RlL,eU$CS
输出结果为: f.CI.aozW
K?I&,t_*R
~Derived x/^zNO\1
vG} oo
~Base ^@> Qiy
+Ea XS
如果析构函数不为虚,那么输出结果为 X Y?@^
)o,0aGo>Of
~Base @=1``z#
}Elce}
1#uw^{n
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 ^!tI+F{n{
xz'd5 re%
仿止该头文件被重复引用