一、#include “filename.h”和#include <filename.h>的区别 .Ajzr8P
9!',b>C6
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 OhZgcUqQ8
7cDU2l
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 F9"w6;hh
_gj&$zP
!|hoYU>@2L
二、头文件的作用 "p&Y^]
2&mGT&HAVA
加强安全检测 hXIro
2jJmE&)7,
通过头文件可能方便地调用库功能,而不必关心其实现方式 r|Z3$J{^"
S^@S%Eg
Yf,K#' h:
三、* , &修饰符的位置 "Mw[P [w*
`_I@i]i^
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 ^ 2GHe<Y
$4kH3+WJ
RcG0 8p.)
四、if语句 8
;d$54
b
r`y ezbG
不要将布尔变量与任何值进行比较,那会很容易出错的。 E:sz$\Ht)
K%<j=c
整形变量必须要有类型相同的值进行比较 n9w9JXp;!
_
nA p6i
浮点变量最好少比点,就算要比也要有值进行限制 TNCgaTJ{h
y.5/?{GL
指针变量要和NULL进行比较,不要和布尔型和整形比较 0]KraLu"N
4'j
sDcs
LZJA4?C
五、const和#define的比较 `g8E1-]l
geQ{EwO8n
const有数据类型,#define没有数据类型 ;{i'#rn{
~7~~S*EQ
个别编译器中const可以进行调试,#define不可以进行调试 e0@6Pd
2XTPBZNe
在类中定义常量有两种方式 Tus}\0/i>
1c3TN#|)W
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; p.ANVA@:
V@>r*7\F
2、 用枚举代替const常量。 ] h-,o
R?e
Zfk*HV#\
.)}@J5P)
六、C++函数中值的传递方式 lzw3= H
,NnhHb2\
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) rG#Z=*b%
/? r?it
void fun(char c) //pass by value >AoK/(yL.
L;gO;vO
void fun(char *str) //pass by pointer Cm$.<CV
gu #-O?B
void fun(char &str) //pass by reference o,U9}_|A
jV.g}F+1m
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 ,Y3W?
Fk(JSiU
函数的类型不能省略,就算没有也要加个void j1_@qns{
<;E
`_b`kzJ
七、函数体中的指针或引用常量不能被返回 hN['7:bQ
3qY K_M^[
Char *func(void) V"p!Bf
1;Pv0&[q/
{ >zDF2Y[
h;=6VgXZ
char str[]=”Hello Word”; DI!V^M[~u
Gpm{m:$L
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 q o<&J f
*x)Ozfe
return str; UzXE_S
pO8ePc@=D
} >iS`pb
Yvn\xph3
函数体内的指针变量并不会随着函数的消亡而自动释放 -(O-%
_qbIh
{Fzs@,|W.
八、一个内存拷贝函数的实现体 f;}EhG'
!"e5~7
void *memcpy(void *pvTo,const void *pvFrom,size_t size) }g$(+1g
G^q3Z#P
{ gM [w1^lj
m*$|GW9
assert((pvTo!=NULL)&&(pvFrom!=NULL)); 5{n*"88
5K|"\
byte *pbTo=(byte*)pvTo; //防止地址被改变 Ed9Z9
}I@L}f5N
byte *pbFrom=(byte*)pvFrom; Ou{v/'9z,
##Z_QB(;
while (size-- >0) b;)~wU=
L`th7d"
pbTo++ = pbForm++; J9K3s_SN
^(*n]
return pvTo; oI^4pwn h
#Rg|BfV-
} p{PE@KO:
-s9P8W
7}*6#KRG
九、内存的分配方式 WM)-J^)BJ
9;?UvOI;
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 54rkC/B>
C>[Uvc
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 #
O4gg
JHf
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 *D'$"@w3
q~o,WZG
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 +za8=`2o
U^qt6$bK
S1/`th
十、内存分配的注意事项 w[6J
`
: Sq?a0!S
用new或malloc分配内存时,必须要对此指针赋初值。 0%)i<a!_Z
~4?9a(>3
用delete 或free释放内存后,必须要将指针指向NULL 4A9{=~nwT
?|:BuHkT
不能修改指向常量的指针数据 O@?kT;B
7Sz?S_N/j
F @Te@n
十一、内容复制与比较 iD= p\
>Z1q j>
//数组…… \6;=$f/?t
4mn&4e
char a[]=”Hello Word!”; y>*xVK{D
S$2b>#@UJ
char b[10]; K(XN-D/c
8u!"#S#>a
strcpy(b,a); *m2=/Sh
*Z_C4Tj
if (strcmp(a,b)==0) iMfngIs |
XJ2^MF2BU
{} \;rYo.+
3=W!4
//指针…… %%cHoprDa
y^7}oH _
char a[]=”Hello Word!”; vP+@z-O
n ]dL?BJ
char *p; pH`44KAuM
@-OnHE
p=new char[strlen(a)+1]; KRjV}\}
4e;QiTj
strcpy(p,a); J<Pw+6B~
BcD&sQ2F
if (strcmp(p,a)==0) #$3yz'"QF
G<M:Ak+~
{} s&GJW@
|
udeoW-_
i|1^+;
十二、sizeof的问题
xG;-bJu
D/h/Y) Y
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 Jjl`_X$CB
)Fb>8<%
char a[]=”Hello World!” 4[r/}/iGo
Kt0(gQOr0
char *p=a; ?'"X"@r5
9;xM%
count<<sizeof(a)<<end; //12字节 TNJG#8 n%Y
MQKfJru7
count<<sizeof(p)<<endl; //4字节 .5!t:FPOv
uytE^
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 Et_V,s<|
0| ;
.6\
void fun(char a[1000]) YIR
R=qpn
jSc#+_y
{ xAggn
% >;#9"O4
count<<sizeof(a)<<endl; //输出4而不是1000 :NJ(r(QG>
?bw4~
} KR"M/#
Xv@SxS-5l
L4L2O7
十三、关于指针 wb Iq&>p
kF>o.uSV
1、 指针创建时必须被初始化 {)AMw q
>hH0Q5aL
2、 指针在free 或delete后必须置为NULL ,ZS6jZ
!a$ D4(`v
3、 指针的长度都为4字节 mXUYQ82
,sGZ2=M}J
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 FYS/##r
upvS|KUil
char *p=new char[100]; -R>}u'EG>
X\}Y
strcpy(p,”Hello World”); 81*M= ?
~SvC[+t+U
delete []p; //注意前面的[]号 5Zw1y@k(
%6--}bY^
p=NULL; p\{-t84n
bqQq=SO
5、数组指针的内容不能超过数组指针的最大容易。 [yj).*0
BnRN;bu
如: NzKUtwnIz
Ej7 /X ~
char *p=new char[5]; Blq8H"3!:
pWu LfX
strcpy(p,”Hello World”); //报错 目标容易不够大 34!dYr%
RI2f`p8k
delete []p; //注意前面的[]号 'Peni1_
>R/$1e1Y
p=NULL; 1N2,mo?2
_Jv
9F8v
&Z?ut*%S
十四、关于malloc/free 和new /delete 6oSQQhge
c%*($)#
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 8}w6z7e|{
2&Nb
l 注意:malloc/free是库函数,new/delete是运算符 =uDgzdDyE
-*2Mf Mh
l malloc/free不能执行构造函数与析构函数,而new/delete可以 &_5tqh
1c+]gIe
l new/delete不能在C上运行,所以malloc/free不能被淘汰 {YUIMd!Y
[7m1Q<
l 两者都必须要成对使用 ny-7P;->8
/=uMk]h
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 PCn Q_A-Q
G;3~2^lB\
zY+Fl~$S
十五、C++的特性 >+5?F*`\D*
;V<iL?
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 DP/J(>eG
pdd/D
重载和内联:即可用于全局函数,也可用于类的成员函数; #E0t?:t5bk
V0nn4dVO
Const和Virtual:只可用于类的成员函数; 2k6 X,
1+`l7'F
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 ^w~23g.
qz4^{
覆盖是指派生类函数覆盖基类函数 CXtU"X
t?nX=i*~]
函数名相同; %7`f{|.
!QmzrX}h
参数相同; qW 1V85FG
G,= yc@uq
基类函数必须有Virtual关键字; p
(FlR?= S
k#bu#YZk
不同的范围(派生类和基类)。 JN6-Z2
bN^O}[
隐藏是指派生类屏蔽了基类的同名函数相同 c.\O/N
9t@:4O
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 ~](fFa{
OPBt$Ki
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 ^% Q|s#w.
B~'MBBD"
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 0:KE@=
e$c?}3E!z
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 (SVWdgb
-oz`"&%
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 ]<DNo&fw
9]$8MY
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: ,D6v4<jh
m\/(w_/?
将void Func(A a) 改为void Func(const A &a)。 ZWV|# c<G
acd:r%y
而void func(int a)就没必要改成void func(const int &a); 1r r@
mmw^{MK!
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 Q
'(ihUq*k
EPW7+Ve
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 c':ezEaC
C9S@v D+
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; W&:[r/8wA
zBf-8]"^
!e#xx]v3
十六、extern“C”有什么作用? ihT~xt
rg(lCL&:S
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 Uh.Zi3X6}6
!k$}Kj)I
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 vtJV"h?e"3
N12:{U
"%8A:^1
十七、构造函数与析构函数 A{o 'z_zC
uQLlA&I"
派生类的构造函数应在初始化表里调用基类的构造函数; Y^"4?96
m8+(%>+7
派生类和基类的析构函数应加Virtual关键字。 *5%*|>
D}Ilyk_uUw
不要小看构造函数和析构函数,其实编起来还是不容易。 F="z]C;u
V%HS\<$h
#include <iostream.h> 'k&?DZ!
7dh1W@\
class Base ~$O1`IT
09M;}4ev&7
{ SN+S6
Jeqxspn
T
public: %>Xr5<$:&
-U2mfW
virtual ~Base() { cout<< "~Base" << endl ; } sPNfbCOz
(g :p5Rl
}; E(<LvMiCa
+V v+K(lh$
class Derived : public Base z*~YLT&
t0PQ~|H<KV
{ NnxM3*
V'Y{v
public: .
,NB( s`
;~HNpu$
virtual ~Derived() { cout<< "~Derived" << endl ; }
yeD_j/
'Tb0-1S?
}; ?SY<~i<K-
.BTx&AqU
void main(void) {g/wY%u=
dGH_ z8
{ +I|8Q|^SD
X7aXxPCq1
Base * pB = new Derived; // upcast 6(56,i<#/
& %}/AoU
delete pB; TW`mxj_J2
g jG2
} hQh9ok8S
Z$K+
7>^
输出结果为: ucg$Ed
1q~LA[6
~Derived !"4w&bQ
SqB/4P
~Base m>Ux`Gp+
{ctwo X[;
如果析构函数不为虚,那么输出结果为 .+#Lx;})
RJJ1
~Base {KaN,td9
l%"`{
<4F7@q,V
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 ;:#U6?=t
='/Z;3jt]x
仿止该头文件被重复引用