一、#include “filename.h”和#include <filename.h>的区别 zoDZZ%{
PaB!,<A
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 o}Cq.[G4k
H[Q_hY[>V
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 r`\A
nT?
mg:!4O$K
iTo k[uJ}
二、头文件的作用 `s#Hq\C
m`?MV\^
加强安全检测 A1Y7;-D
<G8w[hs
通过头文件可能方便地调用库功能,而不必关心其实现方式 %GEJnJ
&NZfJs
t/o N>mQG
三、* , &修饰符的位置 "VxWj}+]
,{eUP0]
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 w) ]H ^6
4 {GU6v)f
4\5uY
四、if语句 QrG`&QN
gIEl.
不要将布尔变量与任何值进行比较,那会很容易出错的。 U!5)5c}G
neF]=uCWnT
整形变量必须要有类型相同的值进行比较 bF}V4"d,B3
`<" m%>
浮点变量最好少比点,就算要比也要有值进行限制 9Mm!%Hu
yR~-k?7b
指针变量要和NULL进行比较,不要和布尔型和整形比较 i7[uLdQ
`BFIC7a
:VmHfOO
五、const和#define的比较 kdx
y\
jA
2
+5e0/_V
const有数据类型,#define没有数据类型 ZUXr!v/R:1
#%3rTU
个别编译器中const可以进行调试,#define不可以进行调试 W1aa:hEf
C.MoKa3
在类中定义常量有两种方式 1r)kR@!LNG
"I-
w
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; %i0?UpA
$gle8Z-
2、 用枚举代替const常量。 n_D8JF
VzS&`d.h
@gGRm
六、C++函数中值的传递方式 6~meM@
DrW#v-d
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) [|`U6
8}u
-_VG;$,jE
void fun(char c) //pass by value }f>H\iJe
+ bhym+
void fun(char *str) //pass by pointer vdoZ&Tu
@MR?6 n*k
void fun(char &str) //pass by reference !hxIlVd{
v{x{=M]
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 -]G(ms;}/Y
(LAXM
x
函数的类型不能省略,就算没有也要加个void 2i#Sn' 1
(kBP(2V
?|;yVew
七、函数体中的指针或引用常量不能被返回 5-u=o)>
u<ySd?
Char *func(void) eHg3}b2r
"](6lB1Oe
{ 7XrfuG*L$
CENVp"C/`
char str[]=”Hello Word”; lVH<lp_ZtK
f,i5iSYf
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉
Zc&&[g
>:sUL<p
return str; tS# `.F~y
5 +9Ze9
} :bU(S<%M
Ac k}QzXO
函数体内的指针变量并不会随着函数的消亡而自动释放 f5RE9%.#~
u?+bW-D'd
Fr?z"
八、一个内存拷贝函数的实现体 e59dVFug.U
P3tx|:gV
void *memcpy(void *pvTo,const void *pvFrom,size_t size) G1T^a>tj4
Q'apG)0I
{ !v#xb3"/
3.
WF}8
assert((pvTo!=NULL)&&(pvFrom!=NULL)); 8U2dcx:G3
VU|dV\>
byte *pbTo=(byte*)pvTo; //防止地址被改变 j|.} I
V)o,1
byte *pbFrom=(byte*)pvFrom; \J^
1,y&d}GW
while (size-- >0) FeJr\|FT
tY W>t9
pbTo++ = pbForm++; d~tuk4F
l":c
return pvTo; )bO BQbj
G*[P<<je_
} cRvvzX
2R-A@UE2
$.6K!x{(
九、内存的分配方式 i hL/n
05\dl
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 >gtQw!
>v;8~pgO
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 :y]Omp
Y[ reD
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 H!e 3~+)
>P KBo
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 Weoj|0|t
VUU]Pu &
\79X{mcd
十、内存分配的注意事项 4tA_YIv
Die-@z|Y
用new或malloc分配内存时,必须要对此指针赋初值。 $ls[|N:y0l
-OZ 5vH0
用delete 或free释放内存后,必须要将指针指向NULL ^:, l\Y
RH0>ZZR
不能修改指向常量的指针数据 c2l_$p
_hf4A8ak
Kz8:UG(
十一、内容复制与比较 "kMzmo=Pv5
-php6$|
//数组…… Ths_CKwgWY
/ RZR}
char a[]=”Hello Word!”; %9C@ Xl
B=L&bx
char b[10]; j'%4{n
iItcN;;7
strcpy(b,a); q*jNH\|
c{ZY,C&<
if (strcmp(a,b)==0) }Y(]6$uS
3{%LS"c
{} 59uwB('|lH
Y>."3*^
//指针…… :S@1
#(Or|\t
char a[]=”Hello Word!”; Id'RL2Kq*&
T<yP* b2E
char *p; l|`9:H
zZ-wG
p=new char[strlen(a)+1]; ]-o"}"3Ef
eg+!*>GaX
strcpy(p,a); "ceed)(:
Yx'res4e
if (strcmp(p,a)==0) ?C0l~:j7D
dGfVZDsr]
{} tL
SN`6[:
xZ5M/YSyG
wle@vCmr
十二、sizeof的问题 fBtm%f
8{U-m0v
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 FxG7Pk+=
6Z?j AXGSq
char a[]=”Hello World!” iJFs0?*
.ujT!{>v/
char *p=a; yj6@7@l>A
rI$`9d
count<<sizeof(a)<<end; //12字节 `pZs T
^G[
%wV>0gQTf
count<<sizeof(p)<<endl; //4字节 }H4=HDO
G}@#u9
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 j Ib
DH DZ_t:
void fun(char a[1000]) eg"Gjp-4=
_zxLwU1(x
{ ulHn#)
8 S`9dSc
count<<sizeof(a)<<endl; //输出4而不是1000 3Rg}+[b
fyz
nuUl
} egR9AEJvz
O[17";P
s}&bJ"!Z
十三、关于指针 RIM`omM
"yziXT@V
1、 指针创建时必须被初始化 M/PFPJ >`
9n]|PEoAB
2、 指针在free 或delete后必须置为NULL p5=|Y^g !
vqslirC
3、 指针的长度都为4字节 !U_K&f
-
N>MBn
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 gMWBu~;!
HWns.[
char *p=new char[100]; Q0?\]2eet9
gIWrlIV{9
strcpy(p,”Hello World”); mAgF73,3
5\mTr)\R
delete []p; //注意前面的[]号 1:C:?ZC#c
n6WY&1ZE~
p=NULL; 3OyS8`
LL^q1)o
5、数组指针的内容不能超过数组指针的最大容易。 P=N$qz$U
$FH18
如: K)7zKEp`cj
MOn,Db$
char *p=new char[5]; A% Q!^d
pN6%&@) =
strcpy(p,”Hello World”); //报错 目标容易不够大 C<^YVeG
D\~zS`}
delete []p; //注意前面的[]号 -kz4FS
{>3\N0e5
p=NULL; |s7`F%
)'4P.>!!aQ
pnyWcrBf
十四、关于malloc/free 和new /delete 09KcKhFB
%U7.7dSOI;
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 -b&{+= ^c
v7
l 注意:malloc/free是库函数,new/delete是运算符 4 PLk
,:Jus
l malloc/free不能执行构造函数与析构函数,而new/delete可以 #BVtL :x@
$aCd/&
l new/delete不能在C上运行,所以malloc/free不能被淘汰 3FSqd<t;D
#mR4fst
l 两者都必须要成对使用 Mk<Vydds
R;whW:Tx
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 PupM/?57
!"Yj|Nu6
|!|^ v
十五、C++的特性 ! hd</_#
s1Ok|31|
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 Bm$"WbOq*R
5
*}R$
重载和内联:即可用于全局函数,也可用于类的成员函数; &adI (s~
d9*hBm
Const和Virtual:只可用于类的成员函数; uf<@ruN
MvLs%GE%
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 t9
\x%=
"eWk#/
覆盖是指派生类函数覆盖基类函数
@4d)R
i!2TH~zl
函数名相同; oeSN9O
qL6c`(0
参数相同; k-V,~c
~9^)wCM+
基类函数必须有Virtual关键字; <P ,~eX(r
@[<nQZw:
不同的范围(派生类和基类)。 s..lK
"b
c@[:V
隐藏是指派生类屏蔽了基类的同名函数相同 WtQ8X|\`
4EI7W,y
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 %R#L
.xzEAu ;
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 {u{@jp
@}_WE,r
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 8bK|:B#6,
_$NIp `d
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 rt3qdk5U
\]Kh[z0"
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 3uU]kD^
mC&=X6Q]
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: e+v({^k
n8=5-7UT
将void Func(A a) 改为void Func(const A &a)。 # ,uya2!)
%98' @$:0
而void func(int a)就没必要改成void func(const int &a); &wd;EGGT!q
"q}FPJ^l_N
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 bawJ$_O_
76tdJ!4Z
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 \y6OUM2y
/[:dp<
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; #Lsnr.80
O1%pxX'`S
!Bz0^1,L
十六、extern“C”有什么作用? U<"WK"SM
gK#mPcn^
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 EcIE~qs
t$2_xX
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 K]/4qH$:
)m6M9eC
@uo ~nF j,
十七、构造函数与析构函数 V$0dtvGvH
I`[i;U{CK
派生类的构造函数应在初始化表里调用基类的构造函数; i|
\6JpNA:
o:Qv
JcB
派生类和基类的析构函数应加Virtual关键字。 kK8itO
d\e7,"L*Q
不要小看构造函数和析构函数,其实编起来还是不容易。 A[G0 .>Wk
$,I q;*7N
#include <iostream.h> yJuQ8+vgR}
z"D.Bm~ ]
class Base tH=P6vY
,Vd\m"K{
{ u4z&!MT}
fA'qd.{f^
public: ly% F."v
JvYPC
virtual ~Base() { cout<< "~Base" << endl ; } !8 &=y
T5urZq*R
}; +% /s*EC'w
0CSv10Tg
class Derived : public Base Iff9'TE
'c\iK=fl
{ I%|>2}-_U
ntNI]~z&
public: R1&unm0
=U|N=/y#hJ
virtual ~Derived() { cout<< "~Derived" << endl ; } 1+b{}d
Lb LiB*D#s
}; e1//4H::t
.CP&bJP%
void main(void) oYWR')8g
t1E[uu ,V8
{ }68i[v9Njk
G0E121`h
Base * pB = new Derived; // upcast (EPsTox
VDTcR
delete pB; 12Y
E2)h?cs
} x8GJY~:SW
fnx-s{c?
输出结果为: o1nURJ!
(8_\^jJ
~Derived h6dPO"
ETs>`#`6o
~Base r$)w7Gk<
">?vir^
如果析构函数不为虚,那么输出结果为 <\?wAjc,
h gJ[LU| >
~Base |>@W
]CX[
@{Gncy|
E7-@&=]v
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用
Ov<NsNX]
OR[{PU=X
仿止该头文件被重复引用