一、#include “filename.h”和#include <filename.h>的区别 S?nXpYr
5nIm7vlQm
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 EzK,SN#
RE`XyS0Q
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 <!^wGN$f
^-T!(P:
IbQ3*
二、头文件的作用 MWGW[V;
Q9)/INh
加强安全检测 ,qJ/Jt$A
^G{3x
通过头文件可能方便地调用库功能,而不必关心其实现方式 gq`gitu0
$Jo[&,
q#Az\B:
三、* , &修饰符的位置 j{EN %
uWR\#D'
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 zzi%r=%r&
]ERPWW;^
Ia:n<sZU
四、if语句 $x]'6
>=c<6#:s<9
不要将布尔变量与任何值进行比较,那会很容易出错的。 g7@G&Ro9J\
3dNOXk,#
整形变量必须要有类型相同的值进行比较 6=2M[T
wwVK15t
浮点变量最好少比点,就算要比也要有值进行限制 ',nGH|K.
#/t^?$8\\
指针变量要和NULL进行比较,不要和布尔型和整形比较 Pq`]^^=be'
^R\0<\'
$-Q,@Bztq
五、const和#define的比较
q%,q"WU
0EfM~u
const有数据类型,#define没有数据类型 ,g%2-#L%
bb[.Kvq5
个别编译器中const可以进行调试,#define不可以进行调试 oqOv"yLJ:
tsR\cO~/
在类中定义常量有两种方式 F>E'/r*
jgbUZP4J>
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; qsn6i%VH
Fy8KZWim
2、 用枚举代替const常量。 fk,[`n+
=7ul,
fb[f >1|
六、C++函数中值的传递方式 =ZjF5,@
x3O$eKy\|5
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) @U'I_`LL
%CJgJ,pk>
void fun(char c) //pass by value DSad[>Uj],
W4Nbl
void fun(char *str) //pass by pointer #+V-65v
<SmXMruU
void fun(char &str) //pass by reference mR:G,XytxM
ECqcK~h#E
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 Y!* \=h6h
J2 {?P
cs
函数的类型不能省略,就算没有也要加个void A~&Tp
"jly[M}C
5$0@f`sj
七、函数体中的指针或引用常量不能被返回 |=2E?&%?
xM}lX(V!w
Char *func(void) vs;T}'O
(D F{l?4x-
{ Fp..Sjh
6
q:@$$}FjL
char str[]=”Hello Word”; !q;EC`i#
%YLdie6c
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 .^8 x>~
E]V:@/(M'
return str; v+A$CGH96
V|xKvH
} Q-fi(UP
_3- nw
函数体内的指针变量并不会随着函数的消亡而自动释放 V6Ie\+@.\
U`sybtuBP'
hK*:pf
八、一个内存拷贝函数的实现体 z8FeL5.(
1\t}pGSOeh
void *memcpy(void *pvTo,const void *pvFrom,size_t size) KW|X\1H
)3PQ|r'
{ ?it49
4^(u6tX5|+
assert((pvTo!=NULL)&&(pvFrom!=NULL)); )B.NV<m
lR_ 4iyqb
byte *pbTo=(byte*)pvTo; //防止地址被改变 DZKVZ_q
O?|opD
byte *pbFrom=(byte*)pvFrom; 5fuOl-M0W
DJP)V8]!B
while (size-- >0) ~.7r
9MA/nybI
pbTo++ = pbForm++; v`evuJ\3
eU?SLIof[{
return pvTo; H~JPsS;
91|=D
\8aE
} hGyi@0
c<)C3v
:J` *@cDn
九、内存的分配方式 )]~'zOE_
OJe#s;oH
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 WL(u'%5
iHhoNv`MR
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 [4B.;MS(
u6h"=l{
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 Rda o
Es<id}`
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 5-lcz)DO
,9Y{x
*kE2d{h^=C
十、内存分配的注意事项 pv8"E?9,k
,!U5;
用new或malloc分配内存时,必须要对此指针赋初值。 &o*/6X
Vvu+gP'z.
用delete 或free释放内存后,必须要将指针指向NULL A7SBm`XJ)p
"mr;|$Y
不能修改指向常量的指针数据 i3g;B?54
TWE$@/9 )g
M6U/.
n
十一、内容复制与比较 os*QWSs
{tn%HK">
//数组…… @q2If{Tk
'PTWC.C?9
char a[]=”Hello Word!”; .OA_)J7
xB"o
7,
char b[10]; (r,tU(
Iu`eQG
strcpy(b,a); 4KF
1vw
1HK5OT&
if (strcmp(a,b)==0) ~_=ohb{
>v^Bn|_/
{} "P;_-i9O
KIO{6
//指针…… -:wC920+
[X[d`@rXv
char a[]=”Hello Word!”; kr2V
|u,2A1
char *p; ~$} `R=
:{<( )gfk
p=new char[strlen(a)+1]; W_(
-~T? xs0_
strcpy(p,a); v`8dRVN
y)_T!&ze
if (strcmp(p,a)==0) vQCRs!A
F3[3~r
{} PW)XDo7
vhiP8DQ
is_`UDaB
十二、sizeof的问题 f.rc~UI?
qYLOq`<f
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 (m|w&oA/
bj^YB,iSM
char a[]=”Hello World!” z1A[rbe=4w
<EKDP>,~
char *p=a; X?5M)MP+I
p\5DW'
count<<sizeof(a)<<end; //12字节 O@St^o*A}
4RYK9=NH
count<<sizeof(p)<<endl; //4字节 ~9#[\/;"
9Cbf[\J!bq
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 o(5Xj$Z
JJlwzH
void fun(char a[1000]) ;7CE{/Bq.p
$'!r/jV
{ Z'iXuI49
Bgs3sM9
count<<sizeof(a)<<endl; //输出4而不是1000 ka3Jqy4[
sS#Lnj^`%
} ;\yY*
`h+ia/
wlr/zquAE9
十三、关于指针 IKSe X
e-vL!&;2
1、 指针创建时必须被初始化 H/m -$;cF3
CbTYt6DC
2、 指针在free 或delete后必须置为NULL bf]W_I]B
m/l#hp+
3、 指针的长度都为4字节 bm9@A]yP
{iiHeSD
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 D h y
3gZ|^h6
+
char *p=new char[100]; |4NH}XVYJ>
R /J@XP
strcpy(p,”Hello World”); F.ml]k&(m
tEP~`$9
delete []p; //注意前面的[]号 ;QbMVY
h; 105$E1
p=NULL; o#Q0J17i?
>]uV
5、数组指针的内容不能超过数组指针的最大容易。 |~vo
9')
如: :X7"fX
D>wq4u
char *p=new char[5]; kx=.K'd5H
Cw "Y=`
strcpy(p,”Hello World”); //报错 目标容易不够大 pX3Q@3,$
8/cD7O
delete []p; //注意前面的[]号 Y(QLlJ*)/
NU>={9!
p=NULL; u'}SaX]0
?h)Z ;,}
v:0.
十四、关于malloc/free 和new /delete 9C[i#+_3M
luD.3&0n
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 W.b?MPy]
b,U"N-6
l 注意:malloc/free是库函数,new/delete是运算符 $w{!}U 2+-
x#z}A&
l malloc/free不能执行构造函数与析构函数,而new/delete可以 (bnyT?p%
Z}74%
9qE
l new/delete不能在C上运行,所以malloc/free不能被淘汰 B[k {u#Kp
YSi[s*.G
l 两者都必须要成对使用 YB{hQ<W
ht _fbh(l
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 Bu4J8eLx
1"k"<{%
JD1IL` ta;
十五、C++的特性 9AQMB1D*v4
LlAMtw"
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 }!{9tc$<b
];X[x s
重载和内联:即可用于全局函数,也可用于类的成员函数; F!m/n!YR
QRbiO
Const和Virtual:只可用于类的成员函数; PYWp2V/
R$qp3I
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 D90m..\w
[_W#8{
覆盖是指派生类函数覆盖基类函数 7!.#:+rg5#
QR4!r@*=
函数名相同; LliOhr4
D=*3Xd
参数相同;
/~`4a
}T([gc7~
基类函数必须有Virtual关键字; Fljqh8c5
VNKtJmt
不同的范围(派生类和基类)。 @64PdM!L
4LY
kK/:
隐藏是指派生类屏蔽了基类的同名函数相同 -yKx"Q9F
yhnhORSY;
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 + ;u<tA
)+
}\NCFh
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 D*!p8J8Ku
<)01]lKH
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 *xY}?vSs
#gjhs"$~
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 EXt?xiha?
sp%EA=: E
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 Jv*[@
-.k
VKUoVOFvPR
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: &3a1(>(7F
\ZSZ(p#1
将void Func(A a) 改为void Func(const A &a)。 q1C) *8*g
rybs9:_}
而void func(int a)就没必要改成void func(const int &a); cs0;:H*N*
7RW5U'B
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 Ww8<f$
05_aL` &eb
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 =2;2_u?
Zx&gr|)}
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; 0K/?8[#
alu3CE
Q4;eN w
十六、extern“C”有什么作用? r3.A!*!
M[aF3bbN
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 1eiV[z$?
M'Fa[n*b?!
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 3Yu1ZuIR
A6D.bJ)
5LJUD>f9Z
十七、构造函数与析构函数 L< 3U)Gp
4x8e~/
派生类的构造函数应在初始化表里调用基类的构造函数; 7S"W7O1>
{J_1.uN=
派生类和基类的析构函数应加Virtual关键字。 D|zlC,J,
X}XTEk3[
不要小看构造函数和析构函数,其实编起来还是不容易。 |^z?(?w
<G d?,}\
#include <iostream.h> WO=X*One
=b\k$WQ_(
class Base }6YD5?4
!nX}\lw
{ ci]IH]x
6$42-a%b
public: cL/6p0S
!VNLjbee.
virtual ~Base() { cout<< "~Base" << endl ; } :-Gf GL>]
xc|pl!ns
}; ^.']-XjC
kJ^)7_3
class Derived : public Base mM*jdm(!
EP!zcp2' C
{
cM9z b6m
W*D]?hXU;
public: ,{4G@:Fm
be^09'
virtual ~Derived() { cout<< "~Derived" << endl ; } 4}mp~AXy;z
CHeU`!:
}; h( lkC[a&
p8yn? ~]^
void main(void) U%E6"Hg
!uIT5D
{ DyZe+,g;S
=_(i#}"A
Base * pB = new Derived; // upcast z&a%_
]Q*
&.1F\/]k
delete pB; eVRFb#EU0e
eh`s fH
} z^tws*u],5
#g)$m}tv?
输出结果为: l`#XB:#U
z:Sr@!DZ
~Derived %cy]dEL7
K|Q|v39{b
~Base =\jp%A1$
ql
Z()
如果析构函数不为虚,那么输出结果为 +59tX2@Q
p([g/Q
~Base `O:ecPD4M
#2N']VP
;
E Nhy
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 aD
33!
:y
P=Au~2X
仿止该头文件被重复引用