一、#include “filename.h”和#include <filename.h>的区别 y$^.HI02jP
^vH3 -A;*
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 b$Ch2Qz0q
Wr+1G 8
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 "-;l{tL
bu|ecv
LUjev\Re
二、头文件的作用 baVSQtda
' y9yx[P
加强安全检测 QC\][I>
rJ UXA<:2
通过头文件可能方便地调用库功能,而不必关心其实现方式 4;hgi[
(`&`vf
s*0PJ\E2
三、* , &修饰符的位置 fsDwfwil*
H!NyM}jsr
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 Sn lKPd
@^';[P!
1TvR-.e
四、if语句 {,aI0bw;
\dz@hJl:
不要将布尔变量与任何值进行比较,那会很容易出错的。 'l}T_7g
G`HL^/Z*
整形变量必须要有类型相同的值进行比较 QQwD)WG
2"~QI xY=
浮点变量最好少比点,就算要比也要有值进行限制 m% {4
:uD*Q/
指针变量要和NULL进行比较,不要和布尔型和整形比较 krC4O2Fkj
1*"t-+|
<+QX Gz1
五、const和#define的比较 fb 8t9sAI
lc71Pp>
const有数据类型,#define没有数据类型 uWYI p\NN
rK%A=Q
个别编译器中const可以进行调试,#define不可以进行调试 (,gpR4O[
L.uX
在类中定义常量有两种方式 xnW3,:0
hZ0CnY8 '
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; ]S6`",+)<f
oT4A|M
2、 用枚举代替const常量。 k(oHmw
V #0F2GV<,
Y?(kE` R
六、C++函数中值的传递方式 "i\rhX
hZE" 8%\q
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) Nd.+Rs
Vs-])Q?7J
void fun(char c) //pass by value S0\;FmLIc
3TRzDE(J
void fun(char *str) //pass by pointer Awo H d7M
G`B e~NU
void fun(char &str) //pass by reference hpD\,
CfguL@tR.
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 R#ABda9
W)dQyZ>J
函数的类型不能省略,就算没有也要加个void :1q)l
OS k+l
prvvr;Ib
七、函数体中的指针或引用常量不能被返回 %T hY6y(
d`he
Wv^/`
Char *func(void) uES|jU{]b
e6C;A]T2E
{ 8E:8iNbF
2sj[hI
char str[]=”Hello Word”; "K3"s Ec%
:}\w2W E[
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 PuvC
MD
2lVJ"jg
return str; zo,`Vibx<
x;&01@m.
} *=Ko"v
}
Gkz\By
函数体内的指针变量并不会随着函数的消亡而自动释放 "~R,%sYb(
!_Z\K$Ns
ke'aSD
八、一个内存拷贝函数的实现体 d"K~+<V}
;JM%O8
void *memcpy(void *pvTo,const void *pvFrom,size_t size) woCmpCN*I
~=$0=)c
{ ftS^|%p
< Y5pAStg
assert((pvTo!=NULL)&&(pvFrom!=NULL)); (twwDI
v6Vie o=
byte *pbTo=(byte*)pvTo; //防止地址被改变 C|#GODA
x=1Iuc;&3
byte *pbFrom=(byte*)pvFrom; K(&I8vAp
7jss3^.wA
while (size-- >0) /.54r/FN')
[1+ o
pbTo++ = pbForm++; <gvuCydsh
*C/bf)w
return pvTo; Gjhpi5?%8
yQAW\0`
} )qDCh
m<7Ax>
xF:}a:c@H
九、内存的分配方式 'o D31\@I
W9i}w&
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 o!nw/7|
g+g0iS
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 ~.FeLWP
x;Qs_"t];3
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 Gi=sJV
U
+c?x2\
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 @1+gY4g
%y7&~me
%pikt7,Z~
十、内存分配的注意事项 $&fP%p
r;>2L'
用new或malloc分配内存时,必须要对此指针赋初值。 h/'b(9fS
i5PZ )&
用delete 或free释放内存后,必须要将指针指向NULL @u@N&{b5"
.|$:%"O&X
不能修改指向常量的指针数据 @ Sq
=q=S
Sw1z^`
1/JtL>SKE
十一、内容复制与比较 S*aVcyDEP
,@\$PyJ
//数组…… ^bD)Tg5K
L=7Y~aL=
char a[]=”Hello Word!”; sJI"
m'r=Z
'P AIh*qA
char b[10]; `, lnBP3D"
x=S8UKUx
strcpy(b,a); U4$}8~o4
jDO"?@+
if (strcmp(a,b)==0) D+nKQ4
",v!geMvu
{} }s@
i
i?HN
//指针…… (BT{\|,V_m
%%-?~rjI
char a[]=”Hello Word!”;
. r?URC
R!+_mPb=Q*
char *p; w\K(kNd(
KbXENz&C
p=new char[strlen(a)+1]; Eo)
#t{{
r(ZMZ^
strcpy(p,a); pdw;SIoC
B[$L)y'-;
if (strcmp(p,a)==0) ku3(cb!2
dED&-e#
{} iBXS
\yE*nZ
Qi;62M
十二、sizeof的问题 w/oXFs&FK
5/E7@h ,
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 Pb]EpyAW
`Eg~;E:
char a[]=”Hello World!” =C(((T.
(i.7\$4
char *p=a; UhX)?'J
W#bOx0
count<<sizeof(a)<<end; //12字节 k .#I ;7
my}l?S[2d@
count<<sizeof(p)<<endl; //4字节 Z.%0yS_T
"*T4%3dA
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 J=?P`\h
&&>Tfzh
void fun(char a[1000]) Q`zW[Y&]
$/FL)m8.3
{ GlOSCJZ
PNB E
count<<sizeof(a)<<endl; //输出4而不是1000 OnND(YiX
A|`mIma#
} Koi-b
`L
m9!?
>$:_M*5
十三、关于指针 l
Zz%W8"
c>b{/92%
1、 指针创建时必须被初始化 9YvK<i&I
1~ZFkcV_C
2、 指针在free 或delete后必须置为NULL nc9sfH3
V'8Rz#Gc5
3、 指针的长度都为4字节 J,D^fVIw
=5q_aK#i
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 )ZMR4U$+v
'pHxO,vo
char *p=new char[100]; X<<FS%:+
*q*$%H
strcpy(p,”Hello World”); U.pGp]\Q)G
bWg!/K55
delete []p; //注意前面的[]号 Ya29t98Pk
hH~GH'dnaE
p=NULL; #A 7|=E
ld[BiP`B2V
5、数组指针的内容不能超过数组指针的最大容易。 !7n`-#)
EQVa8xt/C
如: PB;j4
Y-.aSc53
char *p=new char[5]; $QnsP#ePN
OjurfVw
strcpy(p,”Hello World”); //报错 目标容易不够大 E]0Qz?
W
9;ie[sU:u
delete []p; //注意前面的[]号 Ge ?Q)N
,*Z/3at}5M
p=NULL; NL-V",gI-~
'kHa_
ke2}@|?t
十四、关于malloc/free 和new /delete w3FEX$`_
q"u,r6ED
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 vu~7Z;y(<j
>">grDX
l 注意:malloc/free是库函数,new/delete是运算符 %+oV-o\ #A
;umbld0
l malloc/free不能执行构造函数与析构函数,而new/delete可以
o('6,D
scPvuHzl
l new/delete不能在C上运行,所以malloc/free不能被淘汰 =kb/4eRg
^+}~"nvD
l 两者都必须要成对使用 sMcN[r
%']`t-N8
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 dMK\ y4#i
-/R?D1kOq
@c=bH>Oz
十五、C++的特性 Pv\-D<&@m
VgO.in^q
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 Ee^>Q*wahw
|XJ|vQGU
重载和内联:即可用于全局函数,也可用于类的成员函数; .RPh#FI6J
[bjP-pX
Const和Virtual:只可用于类的成员函数; Mo]
YJ>P+e\o9
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 X<d`!,bn@
mW1T4rR'
覆盖是指派生类函数覆盖基类函数 ~b})=7 n.
vvP]tRZ
函数名相同; -Xt0=3,
B<jVo%og
参数相同; pDt45
-o+; e3#
基类函数必须有Virtual关键字; 9-EdT4=r,
+THK
Jn!>
不同的范围(派生类和基类)。 _f@nUv*
Tua#~.3}J
隐藏是指派生类屏蔽了基类的同名函数相同 T&->xef=
R0T{9,;[`
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 S'=}eeG
I[P_j`aE
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 {YEGy
ORhvo,.u
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 c Qq78Lo
|9]_<X[ic
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 .QB)Y* z
M 9KoQS
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 [#;CBs5o
m:c .dei5
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: SzyaVBD3
Zo@
将void Func(A a) 改为void Func(const A &a)。
ITfz/d8
~c@@m\C"b
而void func(int a)就没必要改成void func(const int &a); H4uHCkj
,YF1*69
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 5?|yYQM0tK
ilwI qj
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 =$uSa7t#
QZFH>,d
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; yw*|
H T
;8yEhar
D/puK
十六、extern“C”有什么作用? [m(n-MuF
r\$`e7d}!
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 13f'zx(AO
K6N+0#
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 !H~PF*,hY
U P*5M
^a=V.
十七、构造函数与析构函数 ]4]AcJj
YD] :3!MI
派生类的构造函数应在初始化表里调用基类的构造函数; 8BX9JoDi
EKNmXt1
lE
派生类和基类的析构函数应加Virtual关键字。 8p PQ
+f'@
不要小看构造函数和析构函数,其实编起来还是不容易。 BB.120v&N
,y gDNF
#include <iostream.h> :]9CdkaU
GB}!7W"
class Base /hAy1V6
k<y~n*{_
{ `+@r0:G&v
[midNC +,
public: dUkZ_<5''
a"phwCc"%
virtual ~Base() { cout<< "~Base" << endl ; } fwv.^kx
\6;b.&%w2
}; .7> g8
B]:?4Ov
class Derived : public Base =h[;'v{
/~pB_l
{ A\|:hzu+
&90pKs
public: ksF4m_E>YB
F{laA YE
virtual ~Derived() { cout<< "~Derived" << endl ; } pd.5
~z7Fz"o<
}; SbH} cu8
)|KZGr
void main(void) i: 7cdhz
[#+klP$
{ /l;_ xs
ZV$!dHW/
Base * pB = new Derived; // upcast QT\"r T9#
M>u84|`
delete pB; 2tZ\/6G<
2C#b-Y1~N
} yH]w(z5Z
+q] kpkG!
输出结果为: ##'uekSJ
Z._%T$8aJv
~Derived '3TfW61]
bM"d$tl$?'
~Base j4$NQ]e^4
A{)p#K8
如果析构函数不为虚,那么输出结果为 DS0:^TLI
]wEFm;N
~Base vxXrVPU3
_ECH(
%[BOe4[
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 tW%!|T5/
q6eD{/4a1
仿止该头文件被重复引用