一、#include “filename.h”和#include <filename.h>的区别 _ q^JjR
'wjL7PI
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件
Xz!O}M{4
\<%?=C'w~
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 JgMYy,q8t
<_#a%+5d
}CQ)W1mO"
二、头文件的作用 .$zo_~ mR
&+" )~2
+
加强安全检测 5OC{_-
Cznp(z
通过头文件可能方便地调用库功能,而不必关心其实现方式 I(va;hG<o
}{F1Cr
7gQ2dp
三、* , &修饰符的位置 /3o@I5
aA=7x&z@
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 4||dc}I"E
\+>g"';f
.&rL>A2U
四、if语句 N4u-tlA
h 6juX'V
不要将布尔变量与任何值进行比较,那会很容易出错的。 ~y>N JM>1
^v&)z,
整形变量必须要有类型相同的值进行比较 B qcFbY
Rv|X\Wm
浮点变量最好少比点,就算要比也要有值进行限制 [4b_`L
~ekV*,R"
指针变量要和NULL进行比较,不要和布尔型和整形比较 eVRjU
Jj7he(!_1
PDhoCAh
!
五、const和#define的比较 I*0TI@Lo
kz^?!l)X0
const有数据类型,#define没有数据类型 6XI$ o,{
oT*qMLdn
个别编译器中const可以进行调试,#define不可以进行调试 [Mp8"
c52S2f7
在类中定义常量有两种方式 :tT6V(-W
gUrXaD#
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; a[7Lqu
p* tAwl
2、 用枚举代替const常量。 6MmkEU z
5^Ps(8VbS
&5Huv?^a'
六、C++函数中值的传递方式 t{Z:N']H
/EV _Y|(-
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) O_^;wey0}?
cc:,,T/i
void fun(char c) //pass by value wg=-&-
p~17cH4~-f
void fun(char *str) //pass by pointer JQH>{OB
d7qYz7=d
void fun(char &str) //pass by reference /XXy!=1J
~ ":}Rs
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 %Iv*u sXP
,o sM|!,
函数的类型不能省略,就算没有也要加个void {J]x81}*;
7(B"3qF8|
M1J77LfS8
七、函数体中的指针或引用常量不能被返回 a$]i8AeG
.y>G/8_i
Char *func(void) o$k9$H>Na
CQ:38l\`gd
{ Itv}TK
eF
':DLv{R
char str[]=”Hello Word”; %)sG 34
s'=w/os
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 v_I)eac z
UOcO\EA+
return str; o>o! -uf
>rid3~
} TyN]P a
R3@luT]
函数体内的指针变量并不会随着函数的消亡而自动释放 #?fKi$fS;L
l@`Do [
HD153M,
八、一个内存拷贝函数的实现体 Hg2Rcl
i2 G.<(3O
void *memcpy(void *pvTo,const void *pvFrom,size_t size) aW(Hn[}^
G }U'?p
{ <L+y
6B
IRIYj(J
assert((pvTo!=NULL)&&(pvFrom!=NULL)); EJ=ud9
48RSuH
byte *pbTo=(byte*)pvTo; //防止地址被改变 zaG1
[xH Hm5$
byte *pbFrom=(byte*)pvFrom; MhZ\]CAs9
d#-'DO{k
while (size-- >0) %IK[d#HO
$n* wS,
pbTo++ = pbForm++; cCO2w2A[*
;Miag'7
return pvTo; ##BfI`FJ
_7b' i6-
} Q<T+t0G\O-
Uq^-km#a
tWaM+W
九、内存的分配方式 VQ^}f/A
Xsd+5="{N
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 u:M)JG
bL0>ul"
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 Y|~+bKa
D"8 ?4+
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 kn&>4/')
T1i}D"H %
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 oyq9XW~ D
I8Q!`KJ
oe,yCdPs
十、内存分配的注意事项 '|@?R |i0
$$e"[g
用new或malloc分配内存时,必须要对此指针赋初值。 lky5%H
M6XpauR-
用delete 或free释放内存后,必须要将指针指向NULL \`Ow)t:
"g:1br?X,9
不能修改指向常量的指针数据 !U4<4<+
jP}Ix8vc=
#}S<O_
十一、内容复制与比较 R?iC"s!
>*Ctp +X@
//数组…… [(*?
Pd04
char a[]=”Hello Word!”; jKr>Ig=$tA
Mq52B_
char b[10]; cjwc:3
CM
,racmxnv
strcpy(b,a);
IIO-Jr
RiiwsnjC
if (strcmp(a,b)==0) $d5}OI"g
!![HR6"Q
{} &NH[b1NMr
u#nM_UJe
//指针…… Dy|)u1?
'f-8P
char a[]=”Hello Word!”; /Jf}~}JP
:N64FR#
char *p; f f5 e]^,
hj,y l&
p=new char[strlen(a)+1]; Y+ !z]S/x
";;Nc>-Y
strcpy(p,a); v@QfxV2
@G^m+-
if (strcmp(p,a)==0) Hv-f :P O
GD0Q`gWNe
{} OE=.@Ry"
vbEO pYCS
T!Nv
十二、sizeof的问题 Ni>!b6Z`[
w@x||K= Z
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 v,d'SR.
d-`z1'
char a[]=”Hello World!”
::sk)
<lTLz$QE
char *p=a; #Q@~TW
7mA:~- .u
count<<sizeof(a)<<end; //12字节 >hO9b;F}
/~3kkM(Ty
count<<sizeof(p)<<endl; //4字节 JKA%$l0
J~|:Q.Rt`
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 S!h=HE
-8Hv3J'=
void fun(char a[1000]) n!&F%|o^^
vP'#x
{ nrKir
+g&M@8XO&
count<<sizeof(a)<<endl; //输出4而不是1000 ){4 !
zKfY0A R
} RC!9@H5S#
EIF"{,m
6cXZ3;a
十三、关于指针 "f:_(np,
Ou{VDE
1、 指针创建时必须被初始化 wL[{6wL
m1Xc3=Y
2、 指针在free 或delete后必须置为NULL -{ES 36
FD/=uIXH2
3、 指针的长度都为4字节 @ \*Zq
MG vp6/Pd
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 !md1~g$rN
v]y=+* A
char *p=new char[100]; y wmC>`0p
[:8+ +#KD
strcpy(p,”Hello World”); Y_/w}HB
uZa)N-=b2
delete []p; //注意前面的[]号 ht2J, 1t
v+C%t!dx
p=NULL; 0t%`jY~%
;]>a7o
5、数组指针的内容不能超过数组指针的最大容易。 7M<co,"
C(n_*8{
如: ak\[+wQ
rPK 1#
char *p=new char[5]; <xUX&J=;
TGGbO:s3
strcpy(p,”Hello World”); //报错 目标容易不够大 4o<'
fY
2%vG7o,#
delete []p; //注意前面的[]号 {_ {zs!r
vngn^2
p=NULL; Y%^qt]u.8
qVE<voB8
R|[gEavFl
十四、关于malloc/free 和new /delete cH6J:0>W
d "25e"(~F
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 S5[}kfe
7A^L$TY
l 注意:malloc/free是库函数,new/delete是运算符 K_%gda|l+
HjY! ]!4p
l malloc/free不能执行构造函数与析构函数,而new/delete可以 (w` j?c1
[I,s: mn
l new/delete不能在C上运行,所以malloc/free不能被淘汰 DDe`Lb%%
Rbcu5.6
l 两者都必须要成对使用 H@'u$qr$:
]QJ7q}
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 Bh;N:{&^Eu
{bNVNG^
}(!3)k7*
十五、C++的特性 i93^E~q]
3x)jab
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 D!mx &O9
yT[)V[}
重载和内联:即可用于全局函数,也可用于类的成员函数; ,6aF~p;wI|
;N!opg))d<
Const和Virtual:只可用于类的成员函数; 0E#?H0<OeG
cUTG!
P\R
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 Va^(cnwa
yC7lR#N8j0
覆盖是指派生类函数覆盖基类函数 lT_dzO
.9q`Tf
函数名相同; zT ")!Df>'
VBz
G`&NG
参数相同; 5ljEh -
V`}u:t7r
基类函数必须有Virtual关键字; @zT2!C?^L
akzKX}
不同的范围(派生类和基类)。 c]NZGn*
m2[J5n?zLL
隐藏是指派生类屏蔽了基类的同名函数相同 JvYs6u
AE=E"l1]
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 @[bFlqsE
0qL.Rnt
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 e?:1wU
WQsu}_g5y
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 EAoq2_(`a
j:U6q,f]
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 T>w;M?`9K
8Yf=)
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 cC9haxW
EPU3Jban
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: [0lO0ik>G
.:=5|0m
将void Func(A a) 改为void Func(const A &a)。 $Y8iT<nP
4ULdf|o P"
而void func(int a)就没必要改成void func(const int &a); ~R~eQ=8
]3uj~la
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 C)ic;!$Qhb
!*o{xq
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 {}P~nP
w`[`:H_z
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; 8d(l)[GZt
Dlz1"|SF
}j{Z
&(K
十六、extern“C”有什么作用? gUme({h&|
oiQ:&$y
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 'ql<R0g
t? Q
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 XoGOY|2`6
WQMoAPfqL
zN/nKj: Q
十七、构造函数与析构函数 B^/(wHBp
R,8Tt!n
派生类的构造函数应在初始化表里调用基类的构造函数; bd[iD?epD]
x[mh^V5ld
派生类和基类的析构函数应加Virtual关键字。 [Xww`OUsh
3e1%G#fu
不要小看构造函数和析构函数,其实编起来还是不容易。 [ ^gb6W9Y
&;U
F,
#include <iostream.h> p,14'HS%@
f{h2>nEj\
class Base v.c.5@%%o
6E9o*YSk
{ a0's6C
5m\)82s
public: 5>h/LE]"
"8E=*2fcw
virtual ~Base() { cout<< "~Base" << endl ; } I>lblI$7
37*2/N2
}; zb.sh
S 9;FD 3
class Derived : public Base Bnw^W_
<DhuY/o
{ 2\CZ"a#[
Z<'iT%6+r
public: S$/SFB$)~W
60l!3o"p!
virtual ~Derived() { cout<< "~Derived" << endl ; } {dlG3P='`f
q><wzCnRu~
}; 0O(V y y
(O/W`qo
void main(void) $F6GCM3Cx
G`f|#-}
{ gi+FL_8CzU
!ZY1AhGZ
Base * pB = new Derived; // upcast y:k7eE"
S";}gw?r6
delete pB; \/9 O5`u*V
.Dy2O*`
} r9p ((ir
~I]aUN
输出结果为: V!s#xXD }
n>,? V3ly
~Derived f/{ClP.
f'Rq#b@
~Base CIz_v.&:
&UAYYH
如果析构函数不为虚,那么输出结果为 HcpAp]L)
$5@[l5cJU;
~Base ]ClqX;'weJ
CHDt^(oa!B
eWXR #g!%>
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 Wr+1e1[
be [E^%
仿止该头文件被重复引用