一、#include “filename.h”和#include <filename.h>的区别 gmrjCLj
lMlXK4-
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 U-|gtND
=`{!" 6a
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 :egSW2"5S
[=XsI]B\
R{4O*i8#
二、头文件的作用 F[Peil+|`
2< ^B]N
加强安全检测 G;,2cu
K
}/M ~
通过头文件可能方便地调用库功能,而不必关心其实现方式 ;g?5V
V_0e/7}Ya
Dx iCq(;
三、* , &修饰符的位置 "j~=YW+l
.w&{2,a3
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 )D(XDN
Km-lWreTH
As78yfK
四、if语句 QK//bV)
lQ)ZsFs=
不要将布尔变量与任何值进行比较,那会很容易出错的。 oA73\BFfP
a_FJN zL
整形变量必须要有类型相同的值进行比较 ]%G[<zD,1
.lRO;D
浮点变量最好少比点,就算要比也要有值进行限制 g_.BJ>Uv
q"fK"H-j
指针变量要和NULL进行比较,不要和布尔型和整形比较 OHe<U8iu%
AnI ENJ
{5_*tV<I
五、const和#define的比较 eF:6k qg
>WG$!o +R
const有数据类型,#define没有数据类型 RYmk6w!w
3"&6rdF\jB
个别编译器中const可以进行调试,#define不可以进行调试 :aco$ZNH5
0I079fqk<
在类中定义常量有两种方式 Z'!jZF~4p
aS:17+!
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; 9KD2C>d<
7nfQ=?XNK
2、 用枚举代替const常量。 k1B7uA'h"G
c5^i5de
_?`3zm4
六、C++函数中值的传递方式 Rl<~:,D
!d%OoRSU'
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) kXv
-B-wOj
C %y AMQ
void fun(char c) //pass by value P2 f~sx9
Y~bp:FkS
void fun(char *str) //pass by pointer ^yjc"r%B
P}JA"V&
void fun(char &str) //pass by reference 4*d_2:|u
Cv~ t~
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 ejD;lvf
rzY7f: '
函数的类型不能省略,就算没有也要加个void e2 Ba@e-
t~Ds)
Cz m`5
七、函数体中的指针或引用常量不能被返回 Y#NlbKkzu
&c?-z}=G
Char *func(void) x)nBy)<
]D%D:>9|/
{ OZ$u&>916
]%F3 xzOk
char str[]=”Hello Word”; y}nM'$p
.kvuI6H
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 o+q4Vg9&
W!V06.
return str; h"M}Iz~|V?
RhXX/HFk
} xlv:+
_sJp"4?
函数体内的指针变量并不会随着函数的消亡而自动释放 (Q\QZu@
J1P82=$,
nEyPNm)
八、一个内存拷贝函数的实现体 J4xt!RW!
,HY z-sK.
void *memcpy(void *pvTo,const void *pvFrom,size_t size) 7H++ pOF
,k+jx53XV
{ &I <R|a
|&h!#Q{7l
assert((pvTo!=NULL)&&(pvFrom!=NULL)); )6^b\`
:KMo'pL
byte *pbTo=(byte*)pvTo; //防止地址被改变 ke'p8Gz
el5F>)
byte *pbFrom=(byte*)pvFrom; <o^mQq&
c{s<W}3Ds
while (size-- >0) `Nc3I\tCM
hFs0qPVY
pbTo++ = pbForm++; %[&cy'
M\>y&'J-
return pvTo; ;(TBg-LEK
OCY7Bls4
} .@ /5Ln
pcoJ\&&W
.ikFqZ$$
九、内存的分配方式 j#<#o:If
~ m,z|
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 c|hKo[r)
$BkdC'D
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 *M6M'>Tin
^5QSV\X
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 (~zdS.
t.485L%
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 ?gH[tN:=
5-5qm[.;
{- 7T\mj
十、内存分配的注意事项 S'B7C>i`#N
I `p44}D3
用new或malloc分配内存时,必须要对此指针赋初值。 `61VP-r
w9H%u0V?
用delete 或free释放内存后,必须要将指针指向NULL / QSK$ZDC
2gg5:9
不能修改指向常量的指针数据 VL7zU->
}eULcgRG
2Q-kD?PO,
十一、内容复制与比较 Bn-%).-ED
a~:'OW:Q
//数组…… :X,1KR
i,$*+2Z
char a[]=”Hello Word!”; xH; 4lw
_lu.@IX-
char b[10]; UTHGjE
kplyZ
strcpy(b,a); 7?Xfge%\
qwiM.b5
if (strcmp(a,b)==0) i*nNu-g
|A[Le
;,
{} z*I=
| t3_E
//指针…… OI::0KOv
p`T7Y\\#!
char a[]=”Hello Word!”; Qm^N}>e
&AoXv`l4
char *p; li$(oA2
+'y$XR~W {
p=new char[strlen(a)+1]; drNfFx2
y*2:(nI
strcpy(p,a); !xA;(<K[^
`~VV1
if (strcmp(p,a)==0) Y GvtG U-
sj0Hv d9
{} p/4GOU5g
pR; AqDQ
@0-<|,^]
十二、sizeof的问题
AQ'~EbH(
Jd7+~isu~
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 F3;UH%L1
nH/V2>Lm
char a[]=”Hello World!” m80Q Mosp
eM*@}3
char *p=a; b:+.Y$%F-
O{%yO=`r
count<<sizeof(a)<<end; //12字节 _ ?xORzO
h/QZcA
count<<sizeof(p)<<endl; //4字节 C8e{9CF
bmGIxBRq
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 '>@evrG
gY=nU,;
void fun(char a[1000]) 1<Qb"FN!2
-'*B%yy
{ }c:s+P+/
4pduzO'I
count<<sizeof(a)<<endl; //输出4而不是1000 ,1a6u3f,
&?#V*-;^
} oDrfzm|[Y
g-bHf]'
d3St Z~&r!
十三、关于指针 +j%!RS$ko
kL*
DU`
1、 指针创建时必须被初始化 qm{(.b^
wJNiw)C
2、 指针在free 或delete后必须置为NULL pi7W8y
J4;w9[a$
3、 指针的长度都为4字节 p$`71w)'[
HcavA{H
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 X6)-1.T&
=e$<["
char *p=new char[100]; 0r*E$|zZ
!9_HZ(W&
strcpy(p,”Hello World”); |a*VoMZ
*:{s|18Pj
delete []p; //注意前面的[]号 &7VN?ox1
%iPWg
p=NULL; Hbn%CdDk1
KLBU8%
5、数组指针的内容不能超过数组指针的最大容易。 iVTC"v
>B!E 6ah
如: z"Miy
3CL/9C>
char *p=new char[5]; 4>-'w MW")
:PE{2*
strcpy(p,”Hello World”); //报错 目标容易不够大 w9<<|ZaU
BiT
#bg
delete []p; //注意前面的[]号 ?x1sm"]p'
%IL]
Wz<
p=NULL; 6<u=hhL
w$[&ejFb
B52n'.
十四、关于malloc/free 和new /delete !}[}YY?',i
n=J~Rssp
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 wI8
,h,OUo]LIY
l 注意:malloc/free是库函数,new/delete是运算符 R/ix,GC
UTB]svC'
l malloc/free不能执行构造函数与析构函数,而new/delete可以 p!B&&)&db
`?f6~$1
l new/delete不能在C上运行,所以malloc/free不能被淘汰 d9e_slx
"jV:L
l 两者都必须要成对使用 @+Yql
0)F.Y,L
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 E)sC:oO
\kWL:uU
7+
+Fak
十五、C++的特性 X
.,Lmh
*U>"_h T0
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 kb3>q($
IUf&*'_
重载和内联:即可用于全局函数,也可用于类的成员函数; }?G([s56
m';j#j)w
Const和Virtual:只可用于类的成员函数; `(tVwX4
K|L&mL&8
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 YYNh|
2
E$SYXe [,
覆盖是指派生类函数覆盖基类函数 # dA9v7
WbJ|]}hJ\
函数名相同; =z>d GIT1
+pUG6.j%
参数相同;
#zmt x0
1.24ZX
基类函数必须有Virtual关键字; ^AhV1rBB
u00w'=pe)
不同的范围(派生类和基类)。 #qLsAw--Q
\k4tYL5
隐藏是指派生类屏蔽了基类的同名函数相同 uA-1VwW+N
M.FY4~
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 '+EtnWHs
:2t0//@X
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 hY5GNYDh
ycq+C8J+Ep
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 0<i8
;2KD
,V^2Oa
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 ZLDO&}
c,CcKy;+
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 :o3>
1.0:
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: X9
N4
f9K+o-P.h
将void Func(A a) 改为void Func(const A &a)。 p40;@gUug
S>Z07d6 &
而void func(int a)就没必要改成void func(const int &a);
d`gKF
~P7zg!p/q
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 w#v-h3XcF
|LV}kG(2
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 <
]"Uy p
|.*nq
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; 2P/ Sq
]z O6ESH
z0H+Or
十六、extern“C”有什么作用? M!YGv
R
X N0v@V
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 jl>jy6T
lY&Sx{-
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 L35]'Jua
`pb=y}
IG.!M@_
十七、构造函数与析构函数 U?%T~!
1B#iJZ}
派生类的构造函数应在初始化表里调用基类的构造函数; .wV-g:2
^
Paf -/
派生类和基类的析构函数应加Virtual关键字。 k4d;4D?
0.\}D:x(z
不要小看构造函数和析构函数,其实编起来还是不容易。 ,. zHG
%Rt
5$+dNT
#include <iostream.h> -lqD
b@S~
=
class Base 5g%D0_e5
99\lZ{f(
{ n8E3w:A-
mlYkn
public: H|S hi /
\JC_"gqt
virtual ~Base() { cout<< "~Base" << endl ; } Kv)Kn8df
F}.R-j#
}; 'l<