一、#include “filename.h”和#include <filename.h>的区别 /J-:?./
c,\!<4
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 Wg3\hv29
:())%Xu3
#include <filename.h>是指编译器将从标准库目录中开始查找此文件
YjV-70'
^3qo%=i
cc"L> XoK
二、头文件的作用 w,'"2^Cwy
"gR W91
T
加强安全检测 3*DwXH +
lQnl6j
通过头文件可能方便地调用库功能,而不必关心其实现方式 cjd Z.jR2
ylEQeN
DKcg
三、* , &修饰符的位置 \8 I>^4t'/
_B5t)7I
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 &?-LL{W{
Ot]Y/;K
:tv:46+s=
四、if语句 RuW62QSq
J:{$\m'
不要将布尔变量与任何值进行比较,那会很容易出错的。 S @EkrC\4n
.>K):|Opv
整形变量必须要有类型相同的值进行比较 P[.BK
b0~AN#Es
浮点变量最好少比点,就算要比也要有值进行限制 E27N1J+1
;U
+;NsCH
指针变量要和NULL进行比较,不要和布尔型和整形比较 yWs_Z6 b
~"Pu6-\VT
`@Q%}J
五、const和#define的比较 ae)0Yu`*G7
0NN{2"M$p
const有数据类型,#define没有数据类型 tPT\uD#t
XYKWOrkQqa
个别编译器中const可以进行调试,#define不可以进行调试 d" "GG/
Whf7J'
在类中定义常量有两种方式 2 us-s
&*I\~;1
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; q;))3aQe
z)Y<@2V*C
2、 用枚举代替const常量。 &IQp&
$uA?c&
e
N@M(Iw
六、C++函数中值的传递方式 N}Ol`@@#h
JY\8^}'9
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) h48JpZ"
[w%MECTe
void fun(char c) //pass by value 8-N8v
*0
RaKfYLw
void fun(char *str) //pass by pointer `Z3Qx~fx
kKFSCl/g
void fun(char &str) //pass by reference AnbY<&OC1
6,"fH{Bd
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 .b4_O
CGg
~zklrBn&
函数的类型不能省略,就算没有也要加个void iY=M67V
@quNVx(y
_]"5]c&*3
七、函数体中的指针或引用常量不能被返回 'L*nC
T;
OIF0X!
Char *func(void) RLypWjMx$
hcw)qB,s
{ KzQ\A!qG
f6 zT
char str[]=”Hello Word”; gr'M6&>
Dt~Jx\\
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 Y",Fs(
s!\uR.
return str; }+[H~8)5
`U4R%
qhWA
} xw*T?!r=V
1cE3uA7
函数体内的指针变量并不会随着函数的消亡而自动释放 dbTPY`
S~\i"A)4
wVvk{tS
八、一个内存拷贝函数的实现体 $73j*@EQA
v535LwFW
void *memcpy(void *pvTo,const void *pvFrom,size_t size) /r#.BXP
&qki
NS
{ Z!TLWX"
Q 'R@'W9
assert((pvTo!=NULL)&&(pvFrom!=NULL)); :t\pi.uWt
K~A$>0c
byte *pbTo=(byte*)pvTo; //防止地址被改变 $oO9N^6yF
fF208A7U
I
byte *pbFrom=(byte*)pvFrom; .:tAZZ
:)v4:&do
while (size-- >0) k+>-?S,
n'D1s:W^B
pbTo++ = pbForm++; rn
l~i
&pS <4
return pvTo; 4K82%P9a
](3e +JC
} +tL]qOBP
\|Pp%U [
]/!#:
九、内存的分配方式 {n8mE,;M
VLW<"7I 6\
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 *%L:soM'Ll
Rh-e
C6P
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 !/G2vF"
`;-K/)/x
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 ANEW^\
c&.>SR')
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 42aYM!
Qvh: hkR
K1 M s
十、内存分配的注意事项 Xc;W9e(U
(J8(_MF
用new或malloc分配内存时,必须要对此指针赋初值。 Tj}H3/2
J[rpMQ
用delete 或free释放内存后,必须要将指针指向NULL fOEw]B#@
T+7O+X#
不能修改指向常量的指针数据 won;tO]\;@
Uk=jQfA*J
b: UTq
7^
十一、内容复制与比较 [(U:1&x&
M=hxOta
//数组…… mGZ^K,)&OR
Heatt?(RR
char a[]=”Hello Word!”; I/D(gY06<
v'(p."g
char b[10]; _NQMi4 V(
UU')V
strcpy(b,a); aMQfg51W:
t<5$85Y~
if (strcmp(a,b)==0) hnag<=
T)J=lw
{} !L4Vz7C
[F4]pR(
//指针…… XnmQp)nyV
m[6?v;w
char a[]=”Hello Word!”; S%zn {1F
3B#qQ#
char *p; f0+)%gO{
zil^^wT0J
p=new char[strlen(a)+1]; o.IJ4'}aN
SoX\S|}%6[
strcpy(p,a); rnW(<t"
C&Rv$<qc
if (strcmp(p,a)==0) ^$-ID6
^]}+s(
{} 8UiRirw
CX/ _\0G4
Fd!Np7xw
十二、sizeof的问题 wp7<0PP
3Au3>q,
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 gXZl3
ZoJ_I
>uv
char a[]=”Hello World!” 6U|An*
ASA ]7qyO
char *p=a; F
uYjrzmx
OolYQU1_
count<<sizeof(a)<<end; //12字节 SVKjhZK
,*_=w^;Rr
count<<sizeof(p)<<endl; //4字节 6
axe
yOHVL~F
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 s6=jHrdvv
GH ]c
void fun(char a[1000]) [t#xX59
8NCu;s
{ cQM_kV??!
a`/\0~
count<<sizeof(a)<<endl; //输出4而不是1000 "m2g"xa\7
+9EG6"..@H
} 44@yQ?
hO8~Rg
'Lm\ r+$F
十三、关于指针 W}^X;f
PydU.,^7
1、 指针创建时必须被初始化 ]J|]IPXy
;W"=s79
2、 指针在free 或delete后必须置为NULL ;5S'?fj
:Y4m3|
3、 指针的长度都为4字节 JTg:3<L
z{;~$."
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 pE&'Xr#P>
-d'swx2aZ!
char *p=new char[100]; _=Y?' gHH
mf4C68DI@u
strcpy(p,”Hello World”); N{kp^Byim0
jimWLF5Q5"
delete []p; //注意前面的[]号 {N.JA=
|azdFf6A:[
p=NULL; C?OqS+
OoIs'S-Z#
5、数组指针的内容不能超过数组指针的最大容易。 u9c^:Op
yyZs[5Q
如: Uw!N;QsC
>~+qU&'2
char *p=new char[5]; W=-:<3XL
WR:I2-1
strcpy(p,”Hello World”); //报错 目标容易不够大 =&8 Cg
"+dByaY
delete []p; //注意前面的[]号 -K%hug
1iLrKA
p=NULL; >^!)G^B
6j2mr6o
*'l|ws
十四、关于malloc/free 和new /delete f3;.+hJ])
bz'#YM
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 *@+E82D
nNc>nB1
l 注意:malloc/free是库函数,new/delete是运算符 6B8gMO
YP4lizs.
l malloc/free不能执行构造函数与析构函数,而new/delete可以 %96l(JlJ)B
HI\V29
a
l new/delete不能在C上运行,所以malloc/free不能被淘汰 ;0"p)O@s04
tX.fbL@T
l 两者都必须要成对使用 ]@P!Q&V #
UlD]!5NO
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 gcI?)F
/:GeXDJw
!5^&?plC@
十五、C++的特性 Ge_Gx*R
nBg
tK
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 8M6wc394
!kQJ6U
重载和内联:即可用于全局函数,也可用于类的成员函数; _C4N6YdU
a<CJ#B2K
Const和Virtual:只可用于类的成员函数; /w/um>>K.
GNX`~%3KYc
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 Ox%.We5
]_js-+w6
覆盖是指派生类函数覆盖基类函数 Cj5=UUnO
0\KDa$'1k
函数名相同; EC8 Fapy
@Wl2E.)K;
参数相同; D:=Q)Uh0I
wQw&.)T
基类函数必须有Virtual关键字; :8LK}TY7
(Kg( 6E,
不同的范围(派生类和基类)。 AAc*\K
(yO8G-Z0
隐藏是指派生类屏蔽了基类的同名函数相同 "QLp%B,A
N / Fa^[
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 @g%^H)T
78h!D[6
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 WT '?L{
z/P^Bx]r
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 @3_."-d
;y]BXW&l&
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 .vov ,J!Y
,8&ND864v
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 #!7b3 >}
5J2tR6u-(
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: fqm-?vy}
*5z"Xy3J
将void Func(A a) 改为void Func(const A &a)。 q c DJ
fl+dL#]
而void func(int a)就没必要改成void func(const int &a); <7*d2
r}M2t$nv
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 b~Un=-@5a
LA4,o@V`
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。
H$!sK
$0,lE+7*
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; hOR1RB
>o4Ih^VB
n _eN|m?@
十六、extern“C”有什么作用? /c!@ H(^)
s0/y> ok
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 W.7XShwd*2
il~A(`+YO
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 Jl-:@[;
/ TAza9a
Rc#c^F<
十七、构造函数与析构函数 TFI$>Oz|
LPS]TG\
派生类的构造函数应在初始化表里调用基类的构造函数; ;t\C!A6
"W@>lf?"
派生类和基类的析构函数应加Virtual关键字。 k*|WI$
'M=V{.8U
不要小看构造函数和析构函数,其实编起来还是不容易。 r%FfJM@!
l5<&pb#b
#include <iostream.h> qMmhVUx
qs3V2lvYw{
class Base ;G4g;YHy|
f19'IH$n{
{ 6I-Qq?L[H
{33B%5n"
public: UO}Yr8Z;
Q+zy\T
virtual ~Base() { cout<< "~Base" << endl ; } VskdC?yIp
~!#2s'
}; |`Q2K9'4bL
\!df)qdu
class Derived : public Base R:,
|xz
IaYaIEL-
{ A ^X 1
#OVS]Asn}
public: !b?`TUt
2<TpNGXM_
virtual ~Derived() { cout<< "~Derived" << endl ; } \PM5B"MDZ
QP<vjj%
}; "4WwiI9
ANlzF&K
void main(void) !d{Ijs'T
#8i9@w
{ U^d!*9R
M:R|hR{=*
Base * pB = new Derived; // upcast e<duDW$X
r%vO^8FQ
delete pB; gF~#M1!!
O%m>4OdH
} #s0Wx47~
*s6(1S
输出结果为: F~zrg+VDjL
_7N^<'B
~Derived i1DJ0xC]
A ?ij
~Base \ 3FOI
D |9ItxYu
如果析构函数不为虚,那么输出结果为 u8b^DB#+W
~zyD=jxP9
~Base V@`A:Nc_>
Z
lR2
QRlrcauM
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 z~\Y*\f^Y3
5v5K}hx
仿止该头文件被重复引用