一、#include “filename.h”和#include <filename.h>的区别 $yCj80m\
"n]B~D
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 @1n
@KS:d\l}U
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 `Rm B{qgB
&S|laqH
bQ
.y,+
二、头文件的作用 {5%<@<?)
DK)qBxc8
加强安全检测 bJBx~
ut\9@>*J=Q
通过头文件可能方便地调用库功能,而不必关心其实现方式 },f7I^s|
PL8akA#
xc*ys-Nv
三、* , &修饰符的位置 g|r
`L;I/Hp
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 }W|CIgF*
}%XNB1/`
CWDo_g$
四、if语句
{'r*Jb0
ZcdS?Z2k
不要将布尔变量与任何值进行比较,那会很容易出错的。 Wq>j;\3b3
T Z>z5YTv
整形变量必须要有类型相同的值进行比较 `b% /.%]$
GzR;`,_O/
浮点变量最好少比点,就算要比也要有值进行限制 &=7ur
Viw{<VH=
指针变量要和NULL进行比较,不要和布尔型和整形比较 75v*&-
Dl"y|
P4N{lQ.>
五、const和#define的比较 oNEU?+
6"=e+V@
const有数据类型,#define没有数据类型 /aPq9B@
f,uxoAS
个别编译器中const可以进行调试,#define不可以进行调试 h|-r t15
$8eq&_gJ
在类中定义常量有两种方式 i$NnHj|
O42An$}
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; |mM7P^I
hZJ Nh,,w
2、 用枚举代替const常量。 iFDQnt
[t
Cy2X>Tl"<E
+_ G'FD
六、C++函数中值的传递方式 N4}h_mh^'
cK?t]%S
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) 2n7[Op
}i[jJb`bY
void fun(char c) //pass by value #"OKO6]
<zUmcZ
void fun(char *str) //pass by pointer [v&_MQ
+Rvj]vd}&
void fun(char &str) //pass by reference 1`uIjXr(
kP6r=HH@
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 t3WlVUtq3
f9rToH
函数的类型不能省略,就算没有也要加个void `=>Bop)
)I<.DN&
ox*Ka]
七、函数体中的指针或引用常量不能被返回 nxJhK
T
2<O
hO
^
Char *func(void) ;F:(5GBi
-cW5v
{ M-Js"cB[
*rbH|o 8
char str[]=”Hello Word”; -g>27EI5
O{4m-;
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 [DE8s[i-
vKW%l
return str; " c]Mz&z
Z4e?zY
} 8O7JuR
$`Ou *
函数体内的指针变量并不会随着函数的消亡而自动释放 (I+-wki"e
OO$<Wgh
oYF8:PYB
八、一个内存拷贝函数的实现体 jy*wj7fj1
!1l2KW<be
void *memcpy(void *pvTo,const void *pvFrom,size_t size) *0iP*j/]
F3qi$ 3HM
{ %d>Ktf
D"o>\Q
assert((pvTo!=NULL)&&(pvFrom!=NULL)); lDH0bBmd0
Qj=l OhM
byte *pbTo=(byte*)pvTo; //防止地址被改变 XJlun l)(K
w7
QIKsI0
byte *pbFrom=(byte*)pvFrom; `KL`^UqR
)O}x&@Q
while (size-- >0) |%tR#!&[:g
@wg*~"d
pbTo++ = pbForm++; $HH(8NoL
FCIT+8K
return pvTo; KomF)KQ2r
('gjfl
} K.cNx
L*5&hPU
Y,0O&'>
九、内存的分配方式 w@"|S_E
bc&:v$EGy
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 weu'<C
8kqxr&,[
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 b\^.5SEw
|mKd5[$
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 C!.6:Aj
eAl&[_o|S
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 YsTfv1~z#
F"bbU/5
2V
十、内存分配的注意事项 Ek4aC3
hsl Js^
用new或malloc分配内存时,必须要对此指针赋初值。 E7*]t_p"
u?aq'
"t
用delete 或free释放内存后,必须要将指针指向NULL B4{A(-Tc
xWV_Do)z
不能修改指向常量的指针数据 KDY~9?}TM
ucMl>G'!gX
MBa/-fD
十一、内容复制与比较 ;`xu)08a
-m__I U
//数组…… E2\)>YF{P
FUHjY
char a[]=”Hello Word!”; X/.|S57
hZ%Ie%~n
char b[10]; *D\nsJ*g
Nl(Aa5:!
strcpy(b,a); |g7E*1Ie
fCTjTlh
if (strcmp(a,b)==0) ZLO_5#<
G&;W
{} Ds-%\@p
7u!p.kN
//指针…… |_ ;-~bmb
CqF<
BE
char a[]=”Hello Word!”; @4&sL] (q
$+rdzsf)+/
char *p; s~TYzfA
2
OGg`1XX
p=new char[strlen(a)+1]; U"ga0X5
QXF>xZ~
strcpy(p,a); LtNG<n)_BH
zZA I"\;W
if (strcmp(p,a)==0) \;g{qM 8
yhTe*I=Gk
{} AA@J~qd
u
v_Jp9
6)H70VPJ
十二、sizeof的问题 {9)LHX7dN
|_2O:7qe
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 6 C
id*UTY
Tg
char a[]=”Hello World!” :yO)g]KF
*WOA",gZ
char *p=a; e+2!)w)[
?X=9@ m
count<<sizeof(a)<<end; //12字节 O/Da8#S<
R*QL6t
count<<sizeof(p)<<endl; //4字节 KUB"@wUr
/LJ?JwAvg5
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 VCh%v -/
[5:F
void fun(char a[1000]) :egSW2"5S
[=XsI]B\
{ koaH31Q
]1gt|M^
count<<sizeof(a)<<endl; //输出4而不是1000 %*LdacjZ
G;,2cu
K
} jb77uH_
)%)?M
*
lK}F>6^\
十三、关于指针 O@Xl_QNxc!
Oq|pd7fcgm
1、 指针创建时必须被初始化 2\m+
`Ol*"F.+I
2、 指针在free 或delete后必须置为NULL As78yfK
L(}T-.,Slr
3、 指针的长度都为4字节 Nnx"b 5I}n
u\>Ed9^
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 {iHC;a5gb$
eK`n5Z&Y\
char *p=new char[100]; a*=\-;HaZ
3wa }p^
strcpy(p,”Hello World”); Qx$Yj
KWU#Swa`
delete []p; //注意前面的[]号 < R0c=BZ>
bCc^)o/w
p=NULL; 3"&6rdF\jB
i7*4hYY
5、数组指针的内容不能超过数组指针的最大容易。 IOt!A
[ bE9Y;
如: 5Sk87o1E(d
L
+-B,466
char *p=new char[5]; 5(TI2,4
vhdT"7`U
strcpy(p,”Hello World”); //报错 目标容易不够大 ~h0SD(
eEupqOF*:W
delete []p; //注意前面的[]号 !P#lTyz
Y~bp:FkS
p=NULL; &vd9\Pp
v5 $"v?PT
)|'? uN7
十四、关于malloc/free 和new /delete yD5T'np<4
h dPKeqg7
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 t$rWE|+_z
e-\J!E'1F
l 注意:malloc/free是库函数,new/delete是运算符 D",ZrwyJ
2"JIlS;J}7
l malloc/free不能执行构造函数与析构函数,而new/delete可以 nA5v+d-<T
d v"
l new/delete不能在C上运行,所以malloc/free不能被淘汰 w/>k
Fg`r:,(a
l 两者都必须要成对使用 xOPSw|!w
GP[;+xMBh
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 `{8Sr)
cfa#a!Y4
Xy=|qu
十五、C++的特性 */u_RJ
69p>?zn
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 ~Yb5FYE
LeF Z%y)F
重载和内联:即可用于全局函数,也可用于类的成员函数; l*e*jA_>:7
#||^l_
Const和Virtual:只可用于类的成员函数; 4703\
HK
-2{NI.-Xd
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 LD0x 4zm$m
2ed$5.D
覆盖是指派生类函数覆盖基类函数 9l]+rs+
bzF>Efza
函数名相同; ;xS@-</:
m6a`Ok P
参数相同; 6k|o<`~,
HQCxO?
基类函数必须有Virtual关键字; #.'0DWT\-
+C' u!^)
不同的范围(派生类和基类)。
a`
s2 z
c>6dlWTqX
隐藏是指派生类屏蔽了基类的同名函数相同 M%92^;|`
; :4&nJ*qG
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 l=GcgxD+"d
%JF^@\E!|
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 ?#YheML?
@tGju\E"o
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 ($pN OGH
@.0>gmY;:
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 ;h<(vc3@f
@a$_F3W
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 /99S<U2ej
K|,P
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: 1LYz
X;H1
RtO3!dGT.
将void Func(A a) 改为void Func(const A &a)。 >'ev_eAk
iO 9.SF0:
而void func(int a)就没必要改成void func(const int &a); cvxYuP~
"{(|}Cds
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 q!iTDg*$
55q!2>Jh.
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 -@L7!,j
17P5Dr&
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; E:vgG|??
.j^tFvN~L
-LzkM"
十六、extern“C”有什么作用? 0Xo>f"2<f
0,~||H{
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 -UY5T@as
!iv6k~.e'2
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 S!WG|75B
>x?x3 #SX
IR JN
十七、构造函数与析构函数 b3.
qlSI| @CO
派生类的构造函数应在初始化表里调用基类的构造函数; I;1W6uD=
{=K);z
派生类和基类的析构函数应加Virtual关键字。 +@] ,JlYf
@};
vl
不要小看构造函数和析构函数,其实编起来还是不容易。 E? lK(C
H=lzW_(
#include <iostream.h> P* X^)R
!0-KB#
class Base 5PY4PT=G
yz}ik^T
{ B(|*u
RN^<bt{_U
public: #`]`gNB0Yg
:j2?v(jT_l
virtual ~Base() { cout<< "~Base" << endl ; } r=6N ZoZ
lbs0i
}; f/7on|bv
,J6t
1V
class Derived : public Base L|hELWru
k3(q!~a:.}
{ 2#
72B
niA>afo
public: #| pn,/
^F)t>K$0m
virtual ~Derived() { cout<< "~Derived" << endl ; } A"tE~m;"7
*@I/TX'\rY
}; *{:Zdg'~E
k"3@G?JY
void main(void) B>}B{qi|
Ec9%RAxl
{ vpq"mpfkh
q nb#~=x^
Base * pB = new Derived; // upcast a B$x(8pP@
_Z>ny&
delete pB; F MX^k
' !2NSv
} BT)PD9CN(
R]&lVXyH
输出结果为: |.KB
4wKQs&:
~Derived frokl5L@
5BJn_<
~Base ~|G`f\Ln"
c(b2f-0!4
如果析构函数不为虚,那么输出结果为 7@R^B =pb
}<qZXb1
~Base uZM%F)
qeDXG
{[4.<|26
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 q`VkA
\
7{tU'`P>
仿止该头文件被重复引用