一、#include “filename.h”和#include <filename.h>的区别 je=a/Y=%U{
M%P:n/j
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 fJ!R6D
}Oq5tC@$G
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 g(CI;f}y
~V1E0qdAE
hT+_(>hT
二、头文件的作用 GH$ pKB
kJT)r6
加强安全检测 RQ"
,3.R==
5K8^WK
通过头文件可能方便地调用库功能,而不必关心其实现方式 sWnLEw
x7<K<k;s
u <v7;dF|s
三、* , &修饰符的位置 /!XVHkX[
mtcw#D
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 Si;H0uP O
7n<::k\lb
FP4P|kl/9'
四、if语句 #BH*Z(
"'?>fe\qG
不要将布尔变量与任何值进行比较,那会很容易出错的。 T'Dv.h
T%*D~=fQ'
整形变量必须要有类型相同的值进行比较 ":QZy8f9%
tJ$_lk
~6q
浮点变量最好少比点,就算要比也要有值进行限制 t&e{_|i#+
Fd9[pU
指针变量要和NULL进行比较,不要和布尔型和整形比较 z 1X` o
5#E`=C%
#5o(h+w)
五、const和#define的比较 )irEM
-r]W
const有数据类型,#define没有数据类型 ((M>s&\y*Y
hZt!/?dc
个别编译器中const可以进行调试,#define不可以进行调试 V1B5w_^>h'
)MTOU47U
在类中定义常量有两种方式 WOL:IZX%
g}(L;fy>7
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; ?hy&
> /caXvS
2、 用枚举代替const常量。 %6f*{G
w
T{[=oH+
U
z>+2m(
六、C++函数中值的传递方式 -m~#Bq
u;2[AQ.
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) XVZ
draN0vf
void fun(char c) //pass by value
H6/$d
[Y|t]^M
void fun(char *str) //pass by pointer \(2sW^fY
II{&{S'HU
void fun(char &str) //pass by reference VRB;$
P71Lqy)5}A
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 c'yxWZEv
{F.[&/A
函数的类型不能省略,就算没有也要加个void >e$PP8&i_T
86F1.ve
kMN~Y
七、函数体中的指针或引用常量不能被返回 P( 8OQL:
gc$l^`+M
Char *func(void) Lt>IX")
YT(AUS5n
{ -6B4sZpzD
=Jb>x#Y
char str[]=”Hello Word”; H"WprHe
8v%o,"
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 6(ol1
(U
Ta\tYZj$
return str; [ v*ju!
l!u_"I8j5
} XZd,&YiaG
^k9I(f^c-_
函数体内的指针变量并不会随着函数的消亡而自动释放 p0vVkdd
YNi.SXH
2[02,FG
八、一个内存拷贝函数的实现体 9'bwWBf7
+52{-a,>
void *memcpy(void *pvTo,const void *pvFrom,size_t size) 0n{=%Q
P/_['7
{ *J`O"a
/%io+94
assert((pvTo!=NULL)&&(pvFrom!=NULL)); (SAs-
=D"#U#>;7&
byte *pbTo=(byte*)pvTo; //防止地址被改变 d7bS
wL
<wD-qT W
byte *pbFrom=(byte*)pvFrom; }0Ed]
f4|rVP|x
while (size-- >0) IjnU?Bf
`<d }V2rdz
pbTo++ = pbForm++; X=&KayD
13x p_j
return pvTo; >fQMXfoY
h<<v^+m
} ^^ixa1H<
a9V,es"BWQ
ey$&;1x#5
九、内存的分配方式 ;;/{xvQ.1
G]&qx`TBK
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 7HYwLG:\~
jAlv`uB|G"
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 63IM]J
R.<g3"Lm>
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 @`9]F7h5W
'!B&:X)
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 am6L8N
"E4a=YH_
{]4LULq
十、内存分配的注意事项 8Z=R)asGS
7WzxA=*#
用new或malloc分配内存时,必须要对此指针赋初值。 5]:U9ts#
Nu)NqFG,
用delete 或free释放内存后,必须要将指针指向NULL [j+sC*
PLBrP
不能修改指向常量的指针数据 ;#< 0<
1T
n}
E|shs=I
十一、内容复制与比较 SNk=b6`9
Z6MO^_m2
//数组…… QS;f\'1bb
'i|YlMFI g
char a[]=”Hello Word!”; /PXzwP_(A
b^vQpiz
char b[10]; @gK?\URoT
W: z;|FF
strcpy(b,a); aV0"~5
B/Ws_Kv
if (strcmp(a,b)==0) BDQsP$'6QT
4 s9LB
{} &m;*<}X
:e+jU5;]3
//指针…… SOaoo^,O
$M:*T.3
char a[]=”Hello Word!”; A?OQE9'
+R:(_:7
char *p; {R{=+2K!|k
a(ZcmYzXU
p=new char[strlen(a)+1]; P@~yx#G
0jWVp-y
strcpy(p,a); <
I``&>
#fM`}Ij.A
if (strcmp(p,a)==0) VuZr:-K/
Qn2&nD%zi
{} &mM0AA'\?H
Y8t8!{ytg
t"I77aZ$A
十二、sizeof的问题 XQw9~$
n~Lt\K:
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 )D%~`,#pQ
J]r^W)O
char a[]=”Hello World!” bpa?C
[mueZQyI?0
char *p=a; ql~J8G9
%J-GKpo/S
count<<sizeof(a)<<end; //12字节 1G`Pmh@
tfWS)y7
count<<sizeof(p)<<endl; //4字节 Yx`n:0
/G`]=@~
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 |JsZJ9W+J
GTxk%
void fun(char a[1000]) &BSn?
iH'p>s5L
{ 5#z1bu
M )(DZ}
count<<sizeof(a)<<endl; //输出4而不是1000 Rf% a'b
2st3
} #T"4RrR
y8xE
6i
cm+P]8o%{
十三、关于指针 HjwE+: w
JK]PRDyD
1、 指针创建时必须被初始化 ?gXp*>Kg[
1{.9uw"2S
2、 指针在free 或delete后必须置为NULL ]/{)bpu
2B`JGFcdcB
3、 指针的长度都为4字节 cidP|ie^
I(
Mm?9F
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 $<OD31T
V28M lP
char *p=new char[100]; bW:!5"_{H
MpOc
strcpy(p,”Hello World”); ]I6 J7A[
0tJZ4(0
delete []p; //注意前面的[]号 s,_m{ to
/zox$p$?h
p=NULL; EiaW1Cs
Ni7nq8B<
5、数组指针的内容不能超过数组指针的最大容易。 f?)-}\[IR{
gI`m.EH}}N
如: _(zG?]y0P
$Ygue5{c
char *p=new char[5]; JsS-n'gF'
f,Ghb~y
strcpy(p,”Hello World”); //报错 目标容易不够大 H6gSO(U
Kf-JcBsrT
delete []p; //注意前面的[]号 h>bx}$q
7PF%76TO
p=NULL; ,tRj4mx
DIUjn;>k8
bs1Rvx1:J%
十四、关于malloc/free 和new /delete T6kdS]4-
lr$zHI7_`
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 /<BI46B\
:2)/FPL6
l 注意:malloc/free是库函数,new/delete是运算符 bQ5\ ]5M
B|X!>Q<g
l malloc/free不能执行构造函数与析构函数,而new/delete可以 |+"(L#wk
.tr!(O],h
l new/delete不能在C上运行,所以malloc/free不能被淘汰 9Gz=lc[!7
xd0 L{ue.
l 两者都必须要成对使用 >KKMcTOYY
\.}c9*)
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 |gY^)9ei
C9 j|OSgk
a-J.B.A$Z/
十五、C++的特性 -D~%|).'
Z$? #
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 {(?4!rh
-35;j'a
重载和内联:即可用于全局函数,也可用于类的成员函数; /_ajaz%
rQ snhv
Const和Virtual:只可用于类的成员函数; An/|+r\
3irl
(;v
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 )BfAw
YZJyk:H\
覆盖是指派生类函数覆盖基类函数 9-m=*|p
ku
M$UYTTX
函数名相同; o[D9I
hs
S`Rs82>
参数相同; PeEj&4k
zp?`N;
基类函数必须有Virtual关键字; }SCM I4\
-`6+UkOV[x
不同的范围(派生类和基类)。 Y`wSv NU
.6 ?U@2
隐藏是指派生类屏蔽了基类的同名函数相同 Ilm^G}GB
UJ6v(:z<
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 C+&l<
fM&
%vi83%$'4
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 hehFEyx
jmW7)jT8:
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 o*hF<D$Y
b5n'=doR/I
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 )@bQu~Y
;i+#fQO7Q
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 FJ?IUy 6
\Y}8S/]
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: 8, >P
e\75:oQ
将void Func(A a) 改为void Func(const A &a)。 <1M-Ro?5k
,
++ `=o
而void func(int a)就没必要改成void func(const int &a); Kx JqbLUC
r",GC]
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 SByW[JE
` sU/& P
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 Pk)1WK7E
~61v5@
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; VVOd]2{
8}| (0mC
W
`}Rf\g
十六、extern“C”有什么作用? m`r(p"
t\ewHZG"
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 jo@J}`\Zt
N ZSSg2TX#
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 Xla~Yg
8)I^ t81
GR32S=\
十七、构造函数与析构函数 0{ R=9wcc
Ma"]PoP
派生类的构造函数应在初始化表里调用基类的构造函数; 'uEl~> l7
Pgea NK5Y
派生类和基类的析构函数应加Virtual关键字。 Q]>.b%s[
]OzUGXxo~
不要小看构造函数和析构函数,其实编起来还是不容易。 ?FcAXA/J{
czd~8WgOa
#include <iostream.h> u;c?d!E
HHsmLo c4
class Base &:)Wh[
=rX>.P%Q 5
{ Ph>%7M%
^gnZ+`3
public: V~5jfcd
[ibu/W$
virtual ~Base() { cout<< "~Base" << endl ; } ^J;bso`
n.(FQx.F
}; %bfQ$a:
~Jz6O U*z
class Derived : public Base sLAQE64\"
'q:`? nJ^
{ y
h9*z3
?(i{y~
public: LSr]S79N1
Jz e:[MYS
virtual ~Derived() { cout<< "~Derived" << endl ; } mL: sJf
[HZv8HU|
}; A~t
j/yq9
Z?m3~L9L2
void main(void) 6 ~w@PRy
(JFWna0@
{ ?<'}r7D
"1M[5\Ax
Base * pB = new Derived; // upcast 6j LCU%^
g7W"
delete pB; Y`SvMkP)+
_zi|
} wDe& 1(T^
[3|P 7?W/
输出结果为: nc|p )
0.k7oB;f(@
~Derived 81
sG
YteO6A;
~Base IB]l1<
DN5 7p!z
如果析构函数不为虚,那么输出结果为 oEZdd#*;
@i IRmQ
~Base L0WN\|D
bB3powy9
Gu\q%'I
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 6G""I]uT
<l E<f+
仿止该头文件被重复引用