一、#include “filename.h”和#include <filename.h>的区别 'Wv=mBEfZ
'5V2{k$4U
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 KsZXdM/
S<Zb>9pl
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 KNtsz[#b
!o.l:Mr
*M*:3v
0
二、头文件的作用 vO#4$,
(/J$2V5-
加强安全检测 86J7%;^Xa
5;=,BWU
通过头文件可能方便地调用库功能,而不必关心其实现方式 a=LjFpv/]
rYI9?q
LD]>_P83
三、* , &修饰符的位置 4u;db_gX
sWp]Zy
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 \TM%,RC3K
*c} MI
e'&
qp>V\h\
四、if语句 9o7E/wP
Rn={:u4
不要将布尔变量与任何值进行比较,那会很容易出错的。 Hd(|fc{2
MqXN,n+`k
整形变量必须要有类型相同的值进行比较 MH{$"^K
D4?qw$"
浮点变量最好少比点,就算要比也要有值进行限制 V9 <!pMj
%zg&eFRHI
指针变量要和NULL进行比较,不要和布尔型和整形比较 %;0Llxf"
/JPyADi
wTBp=)1)f
五、const和#define的比较 q7-Eu4w
I>X _j)
const有数据类型,#define没有数据类型 \D8d!gr
v%t "N
个别编译器中const可以进行调试,#define不可以进行调试 $N[-ks2{@
q|)8VmVV
在类中定义常量有两种方式 .Y.\D\>~
Bor _Kib
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; DJSSc
e6{}hiM
2、 用枚举代替const常量。 8E`rs)A
Cg NfqT0
B42.;4"T
六、C++函数中值的传递方式 %h;~@- $
Bfw]#"N`
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) =8`,,=P^
*RKYdwnb
void fun(char c) //pass by value A-:58Qau+
{4"!~W
void fun(char *str) //pass by pointer nU$;W
:4|W;Lkd!
void fun(char &str) //pass by reference gD0O7KO
d)m+Hc.
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 2T!pFcc
xcO Si>
函数的类型不能省略,就算没有也要加个void F$Q(2:w
ws:@Pe4AF
T1ZAw'6(K
七、函数体中的指针或引用常量不能被返回 ?[Xv(60]
E.kGBA;a?
Char *func(void) MH|!tkW>:
)24r^21.q
{ `mV&[`NZ
+5(#~
char str[]=”Hello Word”; B5"(NJ;
!%n3_tZC
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 |<&9_Aq_
[>xwwm
return str; w4Nm4To
3 A2X1V"
} HJT}v/FZ
^`NU:"
函数体内的指针变量并不会随着函数的消亡而自动释放 fvKb0cIx]
1t{h)fwi
C*kGB(H7
八、一个内存拷贝函数的实现体 zg,?aAm
!P7&{I,e
void *memcpy(void *pvTo,const void *pvFrom,size_t size) ?qwTOi
s-]k 7a2V
{ h?[3{Z ^
5tI4m#y2
assert((pvTo!=NULL)&&(pvFrom!=NULL)); :lQl;Q -e
D. !m*oq
byte *pbTo=(byte*)pvTo; //防止地址被改变 4;@|tC|u
i_?";5B"
byte *pbFrom=(byte*)pvFrom; v[VUX69
7)sEW#d!
while (size-- >0) Gv(bD6Rz
Gqvnc8V&
pbTo++ = pbForm++; JFe %W?}.D
wb^Yg9
return pvTo; ^Nl)ocHv!
*het_;)+{
} 7r,'a{Rcn
;=piJ%k
7:x%^J+
九、内存的分配方式 =qH9<,p`H
,Oojh;P_
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 =)}m4,LA
"5*n(S{ks
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 8%OS ,Z
9B&QY 2v
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 <I
.p{Z
Cw1Jl5OVZ
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 7Yp;B:5@
+!9&E{pmo
iR
j/Tm*T'
十、内存分配的注意事项 $c4Q6w
\,jrug<C$^
用new或malloc分配内存时,必须要对此指针赋初值。 v%c r
5m2(7FC%su
用delete 或free释放内存后,必须要将指针指向NULL WK5~"aw
6kH47Yc?
不能修改指向常量的指针数据 1{\{'EP{
V*P3C5l
c$aTl9e
十一、内容复制与比较 (3YqM7cqt
O H~X~n-Z
//数组…… udxLHs
&Npv~Iy
char a[]=”Hello Word!”; yIC.JmD*
#q. Q tDz
char b[10]; gbNPD*7g9
BEM_y:#
strcpy(b,a); ZAe>MNtW
r:.5O F}
if (strcmp(a,b)==0) M,1Yce%+}
J5Rr7=:*S
{} DE3>F^ j
[oN}zZP]
//指针…… {?*3Ou
'@'~_BBZP
char a[]=”Hello Word!”; \z!*)v/{-
is&A_C7yg
char *p; s6<`#KFAg
UEmNT9V
p=new char[strlen(a)+1]; S^|Uzc
Y~]E6'Bz
strcpy(p,a); 3f9J!B`n
cQDn_Sjhi
if (strcmp(p,a)==0) a x1
)2T?Z)"hO
{} =&?}qa(P
<-uE pF
V#jFjObTN
十二、sizeof的问题 l{wHu(1
b}'XDw
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 Qj(q)!Ku
.um]1_= \
char a[]=”Hello World!” oj*5m+:>a
t{?U NW
char *p=a; <%klrQya
`?VtB!p@x=
count<<sizeof(a)<<end; //12字节 :Bc)1^I
U085qKyCw
count<<sizeof(p)<<endl; //4字节 De`)`\U
'9cShe
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 .Q
FGIAM
VyK]:n<5Q
void fun(char a[1000]) *=i|E7Irg
7M#2Tze}
{ ~6!{\un
!`S?
count<<sizeof(a)<<endl; //输出4而不是1000 P6w!r>?6N
wic"a
Y<m
} c"R`7P
eaP,MkK&
Bv,u kQ\CH
十三、关于指针 }8cL+JJU
m@o/ W
1、 指针创建时必须被初始化 <;\T
e4g[
xvP<~N-
2、 指针在free 或delete后必须置为NULL "o&_tB;O
ZY-UQ4_|u
3、 指针的长度都为4字节
cl4`FU
?2hoY
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 %lPAq
cA%70Y:AV
char *p=new char[100]; vgRjd1k.\y
&L}e&5
strcpy(p,”Hello World”); 0-#SvTf>;:
[eL?O;@BD
delete []p; //注意前面的[]号 0eq="|n^|
2= FGZa*.
p=NULL; fk-zT
W6f?/{Oo8
5、数组指针的内容不能超过数组指针的最大容易。 n%PHHu
K~gt=NH
如: i)fAm$8#G
'6i"pJ0%
char *p=new char[5]; .Ymoh>JRL
HHa
XK
strcpy(p,”Hello World”); //报错 目标容易不够大 _?Zg$7VJ
WP-?C<Iw
delete []p; //注意前面的[]号 :-HVK^$%
'5zolp%St
p=NULL; v <1d3G=G
~oO>6
xaQ]Vjw
十四、关于malloc/free 和new /delete eqD|3YX
-g8G47piX:
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 9%aBW7@SK
G3]TbU!!T
l 注意:malloc/free是库函数,new/delete是运算符 AcV 2l
'Ba Ba=
l malloc/free不能执行构造函数与析构函数,而new/delete可以 d`9%:2qE
+{Yd\{9
l new/delete不能在C上运行,所以malloc/free不能被淘汰 ; V)pXLE
Wk w.z
l 两者都必须要成对使用 \C;cs&\Q
M]&F1<
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 rvjPm5[t
0<"4W:
&P'cf|KI
十五、C++的特性 [5>f{L!<T<
`tKrTq>
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 4PG]L`J{
Z,AF^,H[
重载和内联:即可用于全局函数,也可用于类的成员函数; x]o~ %h$
nxH+XHv
Const和Virtual:只可用于类的成员函数; KS%LX c('
&u)
R+7bl,
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 RGd@3OjN
V'TBt=!=]
覆盖是指派生类函数覆盖基类函数 M6J~%qF^
9m^"ca
函数名相同; ]6)^+(zU
Gs^hqT;h
参数相同; Wj0=cIb
n[$b k_S
基类函数必须有Virtual关键字; |HhqWja
J`/ t;xk
不同的范围(派生类和基类)。 B3 f Kb#T
Q;A1&UA2
隐藏是指派生类屏蔽了基类的同名函数相同 =+24jHs
+>BLox6
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 ph*9,\c8
akg$vHhK4
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 4cC
[JI>e;l
C:
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 B->3/dp2c'
GG0l\!2)
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 2JY]$$K7
<Uj~S
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 =[]V$<G'w{
@'UbTB!
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: YC(7k7
pW{Q%"W
将void Func(A a) 改为void Func(const A &a)。 M\4pTcz{
SMX70T!'9
而void func(int a)就没必要改成void func(const int &a); 3$x[{\ {
N|t!G^rP
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 D c5tRO
>TZ 'V,
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 iveJh2!#<
)F_0('=t
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; VRe7Q0
@)[Q6w`x
OP:i;%@c
十六、extern“C”有什么作用? aMaICM
KZ8Hp=s
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。
=j,2
c3S}(8g5.
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 i_/A,5TF
}le}Vuy\s
pxf(C<y6_
十七、构造函数与析构函数 rw:z|-r
Uk@du7P1k
派生类的构造函数应在初始化表里调用基类的构造函数; %x}iEqk U
5UWj#|t
派生类和基类的析构函数应加Virtual关键字。 v)+E!"R3.
5"~F#vt
不要小看构造函数和析构函数,其实编起来还是不容易。 6}z-X*
Ax"]+pb
#include <iostream.h> & OO0v*@{
18*M
class Base .DX
m5c=h
{ a^{"E8j
YK xkO
public: n 0/<m.
xxnvz
virtual ~Base() { cout<< "~Base" << endl ; } Jcy{ ~>@7
G5Mo IC
}; pCacm@(hG
CG[2
class Derived : public Base B3AWJ1o
N.~zQVO#R
{ +8xC%eE
%P8*Az&]T
public: t,bQ@x{zVC
<cof
virtual ~Derived() { cout<< "~Derived" << endl ; } ` x|=vu-
1hTE^\W
}; `[)!4Jb
Zk:Kux[7
void main(void) OrC}WMhd
mJU1n
{ 4Tdp;n\F
]z77hcjB1
Base * pB = new Derived; // upcast cFD3
C%RYQpY*c
delete pB; "
""k}M2A
+nAbcBJAl
} o;kxu(>yL'
6 2*p*t
输出结果为: qr@<'wp/
VY#nSF`
~Derived SSQB1c
aPToP.e
~Base Tr@|QNu
$-i(xnU/nl
如果析构函数不为虚,那么输出结果为 +0l-zd\
=w5]o@
~Base ljP<WD
B?nw([4m
(=-6'23q)
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 Q"vhl2RX
"Snt~:W>
仿止该头文件被重复引用