一、#include “filename.h”和#include <filename.h>的区别 z0Z%m@
1B\WA8
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 .jK4?}]
tT._VK]o&R
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 Ew$C
;&9
*yGGBqd
5`_SN74o
二、头文件的作用 6wg^FD_Q
f?)-}\[IR{
加强安全检测 Ws12b$
WfRXP^a
通过头文件可能方便地调用库功能,而不必关心其实现方式 4 H&#q>
DW3G
f,Ghb~y
三、* , &修饰符的位置 CU~PT.
Kf-JcBsrT
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 7x8
yxE
|&4/n6;P$0
MfkN]\Jyw
四、if语句 kSo"Ak!
[.}oyz;}N
不要将布尔变量与任何值进行比较,那会很容易出错的。 ;O#>Y
T6kdS]4-
整形变量必须要有类型相同的值进行比较 ]K%!@O!
N)Z?Z+}h
浮点变量最好少比点,就算要比也要有值进行限制 L4l!96]a
#|``ca54B
指针变量要和NULL进行比较,不要和布尔型和整形比较 /wlEe>i
Ht&YC<X
-%4,@
x`
五、const和#define的比较 @[v~y"tE}
,wPr"U+7
const有数据类型,#define没有数据类型 ~bpgSP"
r@,2E6xn
个别编译器中const可以进行调试,#define不可以进行调试 ]]Ufas9
%N_%JK\{@
在类中定义常量有两种方式 {f p[BF
|gY^)9ei
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; 8a"%0d#
xe$_aBU
2、 用枚举代替const常量。 YA5g';$H*
[a<SDMR
_Bj":rzY
六、C++函数中值的传递方式 ijU*|8n{>
\lNN Msd&
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) M"To&?OI
-35;j'a
void fun(char c) //pass by value SZCze"`[
K"@M,8hb
void fun(char *str) //pass by pointer Uoix
2 8u_!f[
void fun(char &str) //pass by reference h
zn6kbv
9(<@O%YU
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 YZJyk:H\
9-m=*|p
函数的类型不能省略,就算没有也要加个void GsM<2@?
0C,`h`
h!9ei6
七、函数体中的指针或引用常量不能被返回 mRK>U$v
G .4X'
Char *func(void) ]
@fk] ]R
|(^PS8wG
{ f6"Z'{j
ZSm3 XXk
char str[]=”Hello Word”; % %UE+u@J
Y\'}a+:@Ph
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 +x}<IS8
Fv`,3aNB
return str; 6;5Ss?ep
Ilm^G}GB
} Rbv;?'O$L
;YL i{
函数体内的指针变量并不会随着函数的消亡而自动释放 Z;)%%V%o
h2J
x]FJ
BING{ew
八、一个内存拷贝函数的实现体 IMONgFBS
kB%JNMF{A
void *memcpy(void *pvTo,const void *pvFrom,size_t size) y1L,0 ]
}\k"n{!"
{ A\5L
7
C$)onk
assert((pvTo!=NULL)&&(pvFrom!=NULL)); l%i+cO D
x'R`.
!g3
byte *pbTo=(byte*)pvTo; //防止地址被改变 \Y}8S/]
9(wK@
byte *pbFrom=(byte*)pvFrom; Wo=jskBrQ
`Ryp% Bn
while (size-- >0) <1M-Ro?5k
Aq7osU1B
pbTo++ = pbForm++; @7n"yp*"
j"Pv0tehw
return pvTo; h@@=M
sCHJ&>m5-
} NQ2E
D.XvG _
FzC'G57Kl
九、内存的分配方式 GWip-wI
KKf
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 P7/X|M z
FaJ &GOM,
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 W
`}Rf\g
E-g_".agO
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 t\ewHZG"
}JAG7L&{
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 )53y
AyP
Xla~Yg
65^9
十、内存分配的注意事项 _:27]K:
x-3\Ls[I
用new或malloc分配内存时,必须要对此指针赋初值。 <2qr}K{'A
'2^Q1{ :\
用delete 或free释放内存后,必须要将指针指向NULL 6)Lk-D
tIgN$BHR>
不能修改指向常量的指针数据 i~J'% a<Qp
cYt!n5w~W
6!FQzFCZq
十一、内容复制与比较 4HA<P6L
A3@6N(
//数组…… cExS7~*
*;*r8[U}q
char a[]=”Hello Word!”; 3m)y|$R
um0N)&iY
char b[10]; P";'jVcR
0lR5<^B
strcpy(b,a); ~e@z;]CiY
TRq6NB
if (strcmp(a,b)==0) yz8jw:d^-
v_-dx
{} gB'6`'
Q'0d~6n&{
//指针…… 6NHX2Ja
&.?'i1!
char a[]=”Hello Word!”; n.(FQx.F
@MCg%Afw
char *p; ,nm*q#R,0
[q #\D
p=new char[strlen(a)+1]; C~iL3Cb
Dm<A
^u8
strcpy(p,a); ySDH"|0
n7-6-
#
if (strcmp(p,a)==0) <e</m)j
y
h9*z3
{} {{p7 3
'u
X}\:_/
3/n5#&c\4
十二、sizeof的问题 Jz e:[MYS
RrQJ/ts7}
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 )P|),S,;Z
"LTad`]<Ro
char a[]=”Hello World!” .0]<k,JZZ
"a U
aotx
char *p=a; Y/zj[>
QMb Ouw
count<<sizeof(a)<<end; //12字节 (JFWna0@
,nDaqQ-C!!
count<<sizeof(p)<<endl; //4字节 yaH
Zt`Y
O@C@eW#
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 E=!\z%4
>I&5j/&}+
void fun(char a[1000]) @6T/Tdz
^$hH1H+V
{ pcWPH.
v^ VitLC
count<<sizeof(a)<<endl; //输出4而不是1000 :G%61x&=Zc
$ gS>FJ
} @2 fg~2M1
E09:E
iAIuxO
十三、关于指针 | h#u^v3
^3L0w}#
1、 指针创建时必须被初始化
7E~;xn;
|_@>*Vmg
2、 指针在free 或delete后必须置为NULL IB]l1<
uk<9&{
3、 指针的长度都为4字节 )|=j`jCC
]-/VHh
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 ?2Py_gkf
:! !at:>
char *p=new char[100]; L0WN\|D
b!5~7Ub.No
strcpy(p,”Hello World”); XuM'_FN`A<
2!=f hN
delete []p; //注意前面的[]号 *YuF0Yt
9m~p0 ILh
p=NULL; *wB1,U{
4u})+2W
5、数组指针的内容不能超过数组指针的最大容易。 n8ZZ#}Nhg
q'Tf,a
如: '@k+4y9q?
%aVq+kC h
char *p=new char[5]; x-&@wMqkc
'kO!^6=4M
strcpy(p,”Hello World”); //报错 目标容易不够大 8NAON5.!
);&:9[b_
delete []p; //注意前面的[]号 4)urU7[ &)
%^1V4
p=NULL; >jc [nk
]K,Tnyp
z/@slT
十四、关于malloc/free 和new /delete Od,qbU4O
9N3o-=
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 p]2128kqx
>V8-i`
l 注意:malloc/free是库函数,new/delete是运算符 )cMh0SGcM1
fN1-d&T
l malloc/free不能执行构造函数与析构函数,而new/delete可以 LIF7/$,0
)W
_v:?A9
l new/delete不能在C上运行,所以malloc/free不能被淘汰 3K0A)W/YEs
o9yJf#-En
l 两者都必须要成对使用 dn$!&
w-L=LWL\
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 PmEsN&YP]
3eAX.z`D
}Sh?S]]`
十五、C++的特性 mLLDE;7|}
]:k/Y$O2
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 M\Ye<Tk
HJ[c M6$2
重载和内联:即可用于全局函数,也可用于类的成员函数; uo%)1NS!
#yF&X(%
Const和Virtual:只可用于类的成员函数; a fW@T2
L2i_X@/
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 Pw`8Wj
wIaony
覆盖是指派生类函数覆盖基类函数 ?Z[[2\DR
j[J-f@F \Y
函数名相同; E,x+JeKV
xHLlMn4M
参数相同; r1{@Ucw2
">,|V-H
基类函数必须有Virtual关键字; DgQpHF
+.b,AqJ/
不同的范围(派生类和基类)。 .2Elr(&*h
b&N'C9/8
隐藏是指派生类屏蔽了基类的同名函数相同 3<f}nfB%r?
2E)-M9ds
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 ,Np0wg0
k|PN0&J
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 fW1CFRHH
:vQrOn18p
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 K)|G0n*qS
U@)eTHv}6
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 w(3G&11N?
K+K#+RBK
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 (Y? gn)*t
MKD1V8i
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: t:
;Pj9
Y0dEH^I
将void Func(A a) 改为void Func(const A &a)。 x,@B(9No
GdxnpE
而void func(int a)就没必要改成void func(const int &a); nuMD!qu!nZ
Vl=l?A8
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 a;qryUyG
=M[bnq*\
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。
PQSP&
jB Z&Ad@e
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; Q}K"24`=
s %``H`
M@H;pJ+B
十六、extern“C”有什么作用? Ru!iR#s)!
x$.^"l-vX
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 5o'FS{6U
U!?_W=?
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 ;oKZ!ND
6"5A%{J
qJa H,
十七、构造函数与析构函数 {
Vf XsI
r|fL&dtr
派生类的构造函数应在初始化表里调用基类的构造函数; Ls$D$/:q?
_~J
{wM
派生类和基类的析构函数应加Virtual关键字。 "R1NG?;q
#64-~NVL_
不要小看构造函数和析构函数,其实编起来还是不容易。 (pCrmyB
F Q7T'G![
#include <iostream.h> < #}5IQ5`Z
~IfJwBn-i
class Base tGh~!|P
aFb==73aLw
{ .B]MpmpK
bz2ztH9 n
public: i$:*Pb3mV
v6M6>&RR|
virtual ~Base() { cout<< "~Base" << endl ; } d *|Y
o
HJLG=mU
}; y^,1a[U.
0y" $MC v
class Derived : public Base +\c5]`
^T;*M_
{ ?FeYN+qR
G%AbC"
public: 7uS~MW
0w\zLU
virtual ~Derived() { cout<< "~Derived" << endl ; } l|~A#kq
vMi;+6'n>
}; Jr
,;>
D3Ig>gKo?m
void main(void) ug!s7fo^
J6s`'gFns
{ qo90t{|c
'KS,'%
Base * pB = new Derived; // upcast nQX:T;WL@
z0p*Z&
delete pB; X<`
6Z6'}BDP
} x=hiQ>BIO0
pMx*F@&nU
输出结果为: ?Wr+Q
b9KP( _
~Derived HZzD VCU
G_3O]BMKd)
~Base 1#V_Z^OL
+j`5F3@
如果析构函数不为虚,那么输出结果为 3nIU1e
nA-.mWD_C
~Base ]Yn D
\=?a/
fNli
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 \}u
Y'F
7 S#J>*
仿止该头文件被重复引用