一、#include “filename.h”和#include <filename.h>的区别 RWahsJTu
4Vx+[8W
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 # ,P(isEZ"
zPQ$\$7xB
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 $j
!8?
#'NY}6cb$
d8.ajeN]o
二、头文件的作用 ]7F)bIG[
b]dxlj}
<
加强安全检测 )@c3##Zp)
3o7xN=N
通过头文件可能方便地调用库功能,而不必关心其实现方式 fm6]CU1^
/\~W$.c
`GkRmv*
三、* , &修饰符的位置 i;HH !
TaN
U]j&cFbn5_
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 mCrU//G
R`7n^,
Nz @8
四、if语句 `1_FQnm)
J=L`]XE
不要将布尔变量与任何值进行比较,那会很容易出错的。 DJJZJ}7
eH
`t \n
整形变量必须要有类型相同的值进行比较 | /#'S&!U
s'AQUUrb<
浮点变量最好少比点,就算要比也要有值进行限制 G,/Gq+WX
Ei|0L$NCg
指针变量要和NULL进行比较,不要和布尔型和整形比较 `^f}$R|
7CYH'DL
"DzGBu\
五、const和#define的比较 _"v~"k 90^
intvlki]be
const有数据类型,#define没有数据类型 S r[IoF)
aKD;1|)
个别编译器中const可以进行调试,#define不可以进行调试 Xi*SDy
z}mvX.j7
在类中定义常量有两种方式 .^GFy
r"1A`89
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; o[2Y;kP3*P
M;> ha,x
2、 用枚举代替const常量。 v6KL93
`-5cQ2>"
#VQ36pCd
六、C++函数中值的传递方式 4=UI3 2v3
\4C)~T:*
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) Fv;u1Atiw
(J/>Gy)d
void fun(char c) //pass by value a'm!M:w
)ZviS.
void fun(char *str) //pass by pointer s"#CkG
jf2y0W>6s
void fun(char &str) //pass by reference ?!_u,sT
s%FP6u7[i
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 kzW\z4f
-Zttj /K
函数的类型不能省略,就算没有也要加个void IBzHR[#,^
il=?o f\,i
uFMs^^#
七、函数体中的指针或引用常量不能被返回 !Q[;5Lqt
GsR-#tV@
Char *func(void) X"laZd947>
wYC9~ms-
{ mMn2(
cvn-*Sj
char str[]=”Hello Word”; zkuv\kY/ Z
`6dy
U_f
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 aS3P(s L
ks)fQFSbu
return str; }3bQ>whF
;|2Uf
} 2#,8evH
4u7c7K>\Y
函数体内的指针变量并不会随着函数的消亡而自动释放 Y}85J:q]
ftDVxKDE?S
p{+tFQy
八、一个内存拷贝函数的实现体 8/Lu'rI
n5/ZJur
void *memcpy(void *pvTo,const void *pvFrom,size_t size) oiIt3<BX
aY3pvOV
{ lqhHbB
P?-d[zLA
assert((pvTo!=NULL)&&(pvFrom!=NULL)); qb#V)
wY."Lw> 6
byte *pbTo=(byte*)pvTo; //防止地址被改变 H&"_}
I^6c0`
byte *pbFrom=(byte*)pvFrom; WBIQ%XB'
^!zJf7(+<>
while (size-- >0) B3ohHxHu
J@=!w[v+
pbTo++ = pbForm++; F#zQQ)(Pf
F(0pru4u
return pvTo; t[L2'J.5
C?_t8G./_
} %D%e:se
A- <.#
pO-)x:Wg
九、内存的分配方式 2gK p\!
]~4}(\u
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 r;@:S~
_R>s5|_
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 (7
]\p
>d1aE)?
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 d#M?lS>
\oD=X}UQw(
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 % B7?l
z.Ve#~\
)%-\hl]
十、内存分配的注意事项 zmrX%!CW
E!O(:/*
用new或malloc分配内存时,必须要对此指针赋初值。 jb6ZAT<8
j$JV(fz
用delete 或free释放内存后,必须要将指针指向NULL \Ho#[k=y*/
<3J=;.\6
不能修改指向常量的指针数据 -h.3M0
{/,+_E/
p]J]<QaZD
十一、内容复制与比较 *axza~d
g]TI8&tP!L
//数组…… ]"7El;2z
iIC9rso"Q1
char a[]=”Hello Word!”; pB{ f-M:D
Jq=>H@il
char b[10]; 8?]%Qi
NEjBjLJZ
strcpy(b,a); Jg?pW:}R
@b(gjOE
if (strcmp(a,b)==0) '~!l(&X
q0xE&[C[M
{} 9EY_R&Yq%
R?FtncL%D
//指针…… ]mDsUZf<
LVz%$Cq,0
char a[]=”Hello Word!”; gP"Mu#/D
M KE[Yb?
char *p; ;Ef)7GE@\[
'@1Qx~*]e
p=new char[strlen(a)+1]; ;/]c^y
19.!$;
strcpy(p,a); okW)s*7
OYCFx2{
if (strcmp(p,a)==0) -a#AE|`
3hpz.ISk
{} rea}Uq+po
{ /Q?
Y)-)NLLG;n
十二、sizeof的问题 N"Nd $4
5&7?0h+I
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 S7~l%G>]b
_J$p<
char a[]=”Hello World!” GA*Khqdid
,t,65@3+b
char *p=a; OA5md9P;d
pJ@DHj2@
count<<sizeof(a)<<end; //12字节 KARQKFp!C>
ri_6wbPp
count<<sizeof(p)<<endl; //4字节 /Gu2@m[r
'jO-e^qT
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 za 4B+&JJ
n"VE!`B
void fun(char a[1000]) 0}3'h#33=
7=[O6<+o
{ 9kiy^0
7G
2ZFKjj
count<<sizeof(a)<<endl; //输出4而不是1000 G"R>a w
YSUH*i/%
} t
1'or
'S-"*:$,u
,lG wW8$R
十三、关于指针 WYd,tGz
0BZOr-i
1、 指针创建时必须被初始化 ~.=!5Ry
4BL,/(W]
x
2、 指针在free 或delete后必须置为NULL LfSUY
a[9OtZX<
3、 指针的长度都为4字节 OX`GN#yl
])";Z
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 :jp$X|
~Am
%%$
char *p=new char[100]; aD`e]K ^L
@ dU3d\!}
strcpy(p,”Hello World”); ,#FH8%Yf
@g5]w&o_
delete []p; //注意前面的[]号 4o8HEq!
^ x#RUv
p=NULL; ZQ8Aak
w3hL.Z,kV
5、数组指针的内容不能超过数组指针的最大容易。 0-O.*Q^
@Bwl)G!|
如: s,q!(\{Pv
545xs`Q_
char *p=new char[5]; F?4'>ZW
zL{@LHP
strcpy(p,”Hello World”); //报错 目标容易不够大 ?(hQZR
0e
\0& (q%c
delete []p; //注意前面的[]号 +Rd{ ?)2~
s'w0pZqj
p=NULL; O/"&?)[v
Bd[}A9O[
tHo/uW_~I
十四、关于malloc/free 和new /delete pAL-Pl9z
FCAu%lvZT
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 +N!{(R:"v}
T8oASg!
l 注意:malloc/free是库函数,new/delete是运算符 P Qay
sdb
'Z}$V*
l malloc/free不能执行构造函数与析构函数,而new/delete可以 :
s3Vl
^(B*AE.
l new/delete不能在C上运行,所以malloc/free不能被淘汰 Z@umbyM
8=Ht+Br
l 两者都必须要成对使用 +t6m>IBu
hY'%SV
p
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 .U
{JI\
W%:zvqg
v
'D{abm0
十五、C++的特性 ]d(}b>gR~(
JC3)G/m(03
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 MeS$+9jV(
4\RuJx
重载和内联:即可用于全局函数,也可用于类的成员函数; 2J <Z4Ap
6U]7V
Const和Virtual:只可用于类的成员函数; +r"$?bw'
=Q/i<u
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 7Kjq1zl;
~:Nyv+g,$
覆盖是指派生类函数覆盖基类函数 &*SnDuc
Czn7,KE8X
函数名相同; 2
{0VyLx
aKO@_R,:
参数相同; vA `.8U 0S
qa6up|xUnn
基类函数必须有Virtual关键字; =7>~u
ozG:f*{T
不同的范围(派生类和基类)。 ,j<"~"]
=
pj6Cvq4bD
隐藏是指派生类屏蔽了基类的同名函数相同 @YELqUb*
I&c#U+-A'
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 bHM
.&4G
v2Y=vr
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 B*7o\~5
V}?5=f'
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 9OBPFF
~sD'pS
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 :z7!X.*
'
r/1+.
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 he #iWD'
u1l#k60
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: I(SE)%!%S
I5,Fh>
将void Func(A a) 改为void Func(const A &a)。 HN+z7 Q8hH
o-_a0j
而void func(int a)就没必要改成void func(const int &a); oZCO$a
hv6>3gbr
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 5l#)tX.by
S6
*dp68
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 =*I9qjla[?
.xx9tP}Xy
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; <Coh
&g_
_=b[b]Ec$s
3 0Z;}<)9
十六、extern“C”有什么作用? (;N_lF0
rcOmpgew
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 `/O_6PQ}
(iFhn*/
E
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 JT+P>\\];'
gd*\,P
G(>a LF
十七、构造函数与析构函数 827N?pU$)
UZ$p wjC
派生类的构造函数应在初始化表里调用基类的构造函数; 2rk_ ssvs
XcXd7e
派生类和基类的析构函数应加Virtual关键字。 %/7`G-a.B
.gB*Y!c7
不要小看构造函数和析构函数,其实编起来还是不容易。 .Kx5Kh{
DIY WFVh
#include <iostream.h> N^)OlH
01J.XfCd6
class Base H5n"!!
F9hCT)
{ {,m!%FDL
I?=Q
*og
public: *k/_p^
<H.Ml>q:r
virtual ~Base() { cout<< "~Base" << endl ; } F[lHG,g-
M:A7=rO~
}; TSOt$7-
I$YF55uB
class Derived : public Base wXP1tM8T
a}yJ$6xi
{ MDRSI g
1.+MX(w
public: 3E#acnqn*
fgNEq
virtual ~Derived() { cout<< "~Derived" << endl ; } !cfn%+0
pJqayzV
}; W6Hiqu+
:)+cI?\#
void main(void) "ey~w=B$M
%9IM|\ulp
{ :
"UBeo<Z
*w!H -*`
Base * pB = new Derived; // upcast SQ@@79A
[hs{{II
delete pB; GDk/85cv0$
UXd\Q''
} SgJQH7N
)%*uMuF
输出结果为: vJYy` k^Y
J=()
A+
~Derived c|E
X/?3ifP6I
~Base A w83@U
]R0^
}sI
如果析构函数不为虚,那么输出结果为 xX}vxhN
K2&pTA~OR
~Base -E.EI@"
TK'(\[E
t.NG]ejZ
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 K{N#^L!
REw!@Y."
仿止该头文件被重复引用