一、#include “filename.h”和#include <filename.h>的区别 Vea2 oQq
.}!"J`{W
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 Z0HfrK#oU
=?]H`T:
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 BdBwfH%:
@yp#k>
L/\s~*:M
二、头文件的作用 ])F*)U
0z&]imU
加强安全检测 @+Ch2Lod
.aS`l~6
通过头文件可能方便地调用库功能,而不必关心其实现方式 KUJCkwQ
mq
0 d ea
uH*moVw@5
三、* , &修饰符的位置 }C-K0ba7
Buc{dcL/
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 wW &q)WOi
hOFC8 g
O0^m_
四、if语句 )Y4;@pEU
W]Bc7JM]T+
不要将布尔变量与任何值进行比较,那会很容易出错的。 #gW"k;7P
8/W(jVO(-
整形变量必须要有类型相同的值进行比较 pmda9V4
DO*rVs3'p[
浮点变量最好少比点,就算要比也要有值进行限制 M3q%(!2
kU:ge
指针变量要和NULL进行比较,不要和布尔型和整形比较 tofX.oi+C$
4eVQO%&2
[B~*88T
五、const和#define的比较 de7
\~$
+4L]Z;k
const有数据类型,#define没有数据类型 #aI(fQZe
rhff8C//'
个别编译器中const可以进行调试,#define不可以进行调试 xER-TT#S
|"]#jx*8KC
在类中定义常量有两种方式 {Kh^)oYdd
Fnqj^5
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; z)tULnR8
df\ ^uyD;
2、 用枚举代替const常量。 ^^
>j2=
gXJtk;
2i9FzpC3
六、C++函数中值的传递方式
V.w
L
jk(tw-B
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) ?+)>JvWDz
p
:{,~
1
void fun(char c) //pass by value d1jg3{pwA
'=AqC,\#
void fun(char *str) //pass by pointer 3~q#P
/1@py~ZX
void fun(char &str) //pass by reference !NqLBrcv 0
6JgbJbUi
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 n4XEyCrD
u@]rR&h`
函数的类型不能省略,就算没有也要加个void b=@H5XTZyK
w{8O$4
w
g)dKXsy(F
七、函数体中的指针或引用常量不能被返回 rX(Ol,&oP
E!A+J63zsw
Char *func(void) B,V:Qs6"
pk8`suZ
{ hZIbN9)8A
L;\f^v(
char str[]=”Hello Word”; ]ZR}Pm/CA
dzk1 !yy
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 /07iQcT(
mX2X.ww(4
return str; jXPf}{^
-,186ZVZ
} 4 :phq
^O.` P
函数体内的指针变量并不会随着函数的消亡而自动释放 4Sz2
9\X
/9b+I/xY"
n +v(t
八、一个内存拷贝函数的实现体 |zbM$37?k
*j~ObE_y
void *memcpy(void *pvTo,const void *pvFrom,size_t size) ECsb?n7e
?`=
<*{_o
{ we0haK
c( _R
xLJ
assert((pvTo!=NULL)&&(pvFrom!=NULL)); :W.pD:/=v
RH9P$;.7
byte *pbTo=(byte*)pvTo; //防止地址被改变 \E
{'|
$~e55X'!+
byte *pbFrom=(byte*)pvFrom; ?
KDg|d
L,yq'>*5s
while (size-- >0) 5{gv\S1
}wB!Bx2
pbTo++ = pbForm++; \zh`z/=92
:]JMsa6
return pvTo; )Vz=:.D
vs^)=
} g#Z7ReMw
=qvn?I^/
<S^Hy&MD>
九、内存的分配方式 J``5;%TJp
|w"G4J6ha
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 =}"P;4:
nt%fJ k
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 /2Z7
a|5<L
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 O]XgA0]
T|&u?
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 PYwGGB-
:IO"' b
lDL(,ZZS`
十、内存分配的注意事项 ~\*wt( o
ef@F!s_fI
用new或malloc分配内存时,必须要对此指针赋初值。 +4n}H}9l
>]HvXEdNZ|
用delete 或free释放内存后,必须要将指针指向NULL ta@fNS4
Sim$:5P
不能修改指向常量的指针数据 R2==<"gq
dy ~M5,zn
;Kh[6{ W
十一、内容复制与比较 8%`h:fE
%J+ w9Z
//数组…… Spw^h=o
-k
}LW4
char a[]=”Hello Word!”; "yK)9F[9Mo
I^)_rOgM
char b[10]; Rzyaicj^c
.NJ Ne
strcpy(b,a); dUBf.2ry
610u!_-
if (strcmp(a,b)==0) )8taMC:H^
b\^1P;!'W
{} iL<FFN~{
uF ;8B]"
//指针…… _}j6Pw'
g*-}9~
char a[]=”Hello Word!”; RT2&^9-
-
i{1h"
char *p; ac,<+y7A
o4^#W;%w
p=new char[strlen(a)+1]; BC85#sbl
I-Q(kWc
strcpy(p,a); L<G6)'5W
i)/#u+Y1P
if (strcmp(p,a)==0) (S?qxW?
M<x><U#]A
{} t]{, 7.S
y#P_ }Kfo
E*yot[kj
十二、sizeof的问题 C,8@V`
g2vt(Gf ;
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 mC$ te
?es9j]
char a[]=”Hello World!” VrKLEN\
W6)XMl}n
char *p=a; x&N@R?AG1
m;sYg
count<<sizeof(a)<<end; //12字节 U ZL-mF:)&
.G}$jO}
count<<sizeof(p)<<endl; //4字节 vos-[$
ZSB;4 ?:h
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 fc<,kRp
R0yp9icS
void fun(char a[1000]) _$mS=G(
PKev)M;C+
{ k#2b3}(,
`uc`vkVZ
count<<sizeof(a)<<endl; //输出4而不是1000 eH 9-GGr
rc}=`D`
} rm<`H(cT
Kww+lgzS
m[w~h\FS
十三、关于指针 'h>l_A
i7?OZh*f
1、 指针创建时必须被初始化 4)9Pgp:
{!t6&
A
2、 指针在free 或delete后必须置为NULL L(/wsw~y*
[3]h(D
3、 指针的长度都为4字节 9Z:pss@
'<wZe.Q!
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 kqCUr|M.P
m.U&O=]5
char *p=new char[100]; V^\b"1X7N
?aZ\Dg{
strcpy(p,”Hello World”); <2\QY
i;67<f}-
delete []p; //注意前面的[]号 ^.[+)0I
oTeQY[%$
p=NULL; WhL"-f
jYh.$g<`0+
5、数组指针的内容不能超过数组指针的最大容易。 OQ<NB7'n0A
<$%Y#I'zX
如: VKr
oikz@]
&RlYw#*1.
char *p=new char[5]; 6 w0r)
~gEd(
strcpy(p,”Hello World”); //报错 目标容易不够大 )7F$:*e
s=XqI@
delete []p; //注意前面的[]号 Ucj>gc=
ibgF,N
p=NULL; z.:IUm{z
U}W7[f lc
C2?p>S/q
十四、关于malloc/free 和new /delete h-@_.&P0e
a{iG0T.{Yh
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 B 3eNvUFZg
L_AQS9a^D
l 注意:malloc/free是库函数,new/delete是运算符 y|%lw%cSe
5dLb`Gf
l malloc/free不能执行构造函数与析构函数,而new/delete可以 lW@i,1
zh4m`}p
l new/delete不能在C上运行,所以malloc/free不能被淘汰 t<qXXQ&5
CHM+@lD
l 两者都必须要成对使用 iu'r c/=V
":^cb =
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 R(A"6a8*
!xD_=O
28o!>*
十五、C++的特性 O:X|/g0Y
gd ; e-.
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 }x:nhy`
uX,ln(9I*H
重载和内联:即可用于全局函数,也可用于类的成员函数; @,TCg1@QJ
btB> -pT
Const和Virtual:只可用于类的成员函数; K9UWyM<(2C
:sekMNM
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 >c@1UEwkm
y7#vH<
覆盖是指派生类函数覆盖基类函数 y &%2
dRLvej,
函数名相同; 0bG2YMs
PciiDh~/
参数相同; r/6h}
tJ9`Ys
基类函数必须有Virtual关键字; O0>^?dsL
_ 6'HBE
不同的范围(派生类和基类)。 _qhYG1t
,9ZN k@q
隐藏是指派生类屏蔽了基类的同名函数相同 w77"?kJ9X
w24@KaKFo
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 xr4kBC
t
31}kNc}n
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 zI3Bb?4.
o*|j}hnbv
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 2;=xHt
,46k8%WW
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 <o\I C?A
nK|WzUtp
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 ZIM 5$JdCv
=ZN~*HLl}
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: ]+i~Cbj
i^DZK&B@u
将void Func(A a) 改为void Func(const A &a)。 {KalVZX2R
fwi(qx1=}
而void func(int a)就没必要改成void func(const int &a); `}fwR
NX:i]t
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 -AxO1
qO
Gd%E337d
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 V$fvf#T
WT>2eMK[
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; B@2VI
1%
O9]+Jd4W
V3$Yr"rZ;
十六、extern“C”有什么作用? `>cBR,)r
Ox1#}7`0>
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 [Dq!t1
m`Ver:{
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 T#e ;$\
W{(q7>g
F"Y.'my8
十七、构造函数与析构函数 >HY(
Ij<
_]whHS+
派生类的构造函数应在初始化表里调用基类的构造函数; %^$7z,>;
3@/\j^U
派生类和基类的析构函数应加Virtual关键字。 &z(E-w/S
-r5JP[0kP
不要小看构造函数和析构函数,其实编起来还是不容易。 5J4'\M
8vLaSZ="[
#include <iostream.h> e1j3X\ \
9c@."O`
class Base =
j,Hxq
Y[ciT)
{ TxD,A0
54%@q[-
public: Xo:!U=m/#
0qj:v"~Q
virtual ~Base() { cout<< "~Base" << endl ; } #r}O =izi
_3YuPMaN
}; M3U*'A\
zFqlTUD`t
class Derived : public Base VNcxST15a
wjm _bEi
{ AD=vYDR+
j r<`@
public: <!s+X_^
:d
ts>
virtual ~Derived() { cout<< "~Derived" << endl ; } 8(Ab
NQ
+I {ZW}rA
}; D 1Q@4
g
TUQ+?[
void main(void) #Jo#[-r
uoM;p'
{ 8i=c|k,GL.
>vP DF+ u
Base * pB = new Derived; // upcast *?a rEYc8
Az}.Z'LJ
delete pB; 5mxYzu;#]
u._B7R&>
} `EUufTYi
6{ql.2
Fa
输出结果为: ]c.1&OB7o
1yS[;
~Derived W'BB FG
(|EnRk-E
~Base ]{Ytf'bG
4Y)rgLFj
如果析构函数不为虚,那么输出结果为 *,:>EcDr
q*|H*sS
~Base Sd!!1as
#JFTD[1
PtUea
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 `*J;4Ju@
\<}4D\qz
仿止该头文件被重复引用