一、#include “filename.h”和#include <filename.h>的区别 GE8D3V;*V
)>X|o$2
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 k5%0wHpk =
ywQ!9 \
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 )av'u.]%c
>&Ui*
wI]R+.
二、头文件的作用 Vh.;p.!e
CMxjX
加强安全检测 T.w}6?2
kq}eUY]
通过头文件可能方便地调用库功能,而不必关心其实现方式 zEPx
lF}$`6
o|^?IQ7bpf
三、* , &修饰符的位置 id#k!*$7
z Jo#3
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 E_![`9i
?Str*XA;
k.=S+#"}
四、if语句 6|9g4@Hy
U ygw*+
不要将布尔变量与任何值进行比较,那会很容易出错的。 U3|&Jee
$G-N0LV
整形变量必须要有类型相同的值进行比较 MNf @HG
C@UJOB
浮点变量最好少比点,就算要比也要有值进行限制 |p8"9jN@}c
+%le/Pg@
指针变量要和NULL进行比较,不要和布尔型和整形比较 \A3>c|
l`M5'r]l
ReB(T7Vk=
五、const和#define的比较 sQ>B_Y!
8W1K3[Jj<
const有数据类型,#define没有数据类型 j_6` s!Yw
UP~WP@0F
个别编译器中const可以进行调试,#define不可以进行调试 2*-ENW2
p'%: M
在类中定义常量有两种方式 HV$9b~(
GOZQ5m
-
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; GEe 0@q#YA
Q0L@.`~
2、 用枚举代替const常量。 }4\!7]FVYX
L&DF,fWsF&
}W__ffH
六、C++函数中值的传递方式 #A|D\IhF
dIk8TJ
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) >TlW]st
%eutfM-?6
void fun(char c) //pass by value wzDk{4U
0U~;%N+lv
void fun(char *str) //pass by pointer y;{^Ln4{
t> x-1vf%
void fun(char &str) //pass by reference ElEv(>G*
fd5ZaE#f
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 )y%jLiQv
$TD~k;
函数的类型不能省略,就算没有也要加个void +&7[lsD*
n2xLgK=
kb"_6,[Ms
七、函数体中的指针或引用常量不能被返回 m?D
<{BQ;
Sc4obcw%
Char *func(void) cQ3W;F8|n
L(WL,xnBy
{ S'
(cqO}=F
)h>\05|T
char str[]=”Hello Word”; O6m.t%*
E[|s>Xv~
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 V-KL%
,67"C2Y
return str; /~3N@J
D00G1:Ft(T
} r/NSD$-n
qj~flw1:
函数体内的指针变量并不会随着函数的消亡而自动释放 w(76H^e
gk!E$NyE
z-EwXE
八、一个内存拷贝函数的实现体 Y7<zm}=(/
_BZ1Vnv
void *memcpy(void *pvTo,const void *pvFrom,size_t size) b]!9eV$
,O:EX0
{ o"rq/\ovv
r\$6'+Si
assert((pvTo!=NULL)&&(pvFrom!=NULL)); NFk}3w:
o&(wg(Rv
byte *pbTo=(byte*)pvTo; //防止地址被改变 )y9 ;OA
3lo;^KX !
byte *pbFrom=(byte*)pvFrom; ?e
F@Q!h
Vy-28icZ`
while (size-- >0) K)\(wxv
WtEI] WO
pbTo++ = pbForm++; "-w^D!C
D`6iDit
return pvTo; t#C,VwMe[
^_v[QV
} 6cM<>&e
rh@r\H@j
f|OI`
九、内存的分配方式 =M7TCE
"`pNH'
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 t/}L36@+
9B
/s
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 {fZb@7?GF
]kx-,M(
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 ?w-1:NWjt
+a%xyD:.?
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 z~,mRgc$B
l^\(ss0~
ipobr7G.SD
十、内存分配的注意事项 i[\w%(83Fi
7paUpQit
用new或malloc分配内存时,必须要对此指针赋初值。 zDD4m`2
!xu9+{-
用delete 或free释放内存后,必须要将指针指向NULL 6B0#4Qrv
@}Zd (o
不能修改指向常量的指针数据 YTK^ijmU6x
T-'~? [v
F@Q^?WV
十一、内容复制与比较 Y;Ap9i*
En(7(qP6}
//数组…… #uSK#>H_!
8'A72*dhX
char a[]=”Hello Word!”; W^es;5
^"9*
'vTtc
char b[10]; gY(1,+0-
Tzzq#z&F
strcpy(b,a); _T5)n=|
kZLMtj-
if (strcmp(a,b)==0) v!9i"@<!
W^Y#pn
{} qj!eLA-aD
*RWm47
//指针…… )0k']g5
%v+=;jw
char a[]=”Hello Word!”; Dw_D+7>(v
PFM'&;V
char *p; (CJ.BHu]
`S3>3
p=new char[strlen(a)+1]; nPN?kO=]
n_Onr0EvO
strcpy(p,a); rv>^TR*,!
ujr(K=E
if (strcmp(p,a)==0) S{#cD1>.
S QY"OBo<e
{} C3XmK}h
\,&9
3GH(wSv9\
十二、sizeof的问题 \K
iwUz
kL>d"w
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 N@xg:xr
2;$k(x]
char a[]=”Hello World!”
X[](Kj^`<
t*G/]
char *p=a; -c%dvck^,
F'JY?
count<<sizeof(a)<<end; //12字节 MFt*&%,JX
cXnKCzSxZq
count<<sizeof(p)<<endl; //4字节 $HJTj29/
]m4OIst
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 4)6xU4eBaL
C&~1M}I
void fun(char a[1000]) e>}}:Ud
V\]" }V)"
{ L<V3KS2y
ln!'_\{
count<<sizeof(a)<<endl; //输出4而不是1000 O#a6+W"U
q.#[TI ^
} m#vL*]c}
R\|lt)h
h#r^teui)
十三、关于指针 #R0A= !
BYrZEVM9
1、 指针创建时必须被初始化 6K`c/)
;%C'FV e]
2、 指针在free 或delete后必须置为NULL Q/ms]Du
4mjgt<`
3、 指针的长度都为4字节 Z?P~z07
nlYR-.
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 I04jjr:<
B/JO~;{
char *p=new char[100]; *^\HU=&
iD38\XNMV
strcpy(p,”Hello World”); WEg6Kz
$''?HjB}T
delete []p; //注意前面的[]号 )4>2IQ
^N}Wnk7ks'
p=NULL; vbx6I>\Y
>_dx_<75&
5、数组指针的内容不能超过数组指针的最大容易。 DZ7
gcC
0Sq][W=
如: acP+3u?r
le +R16Z
char *p=new char[5]; \!vN
I:bD~Fb3
strcpy(p,”Hello World”); //报错 目标容易不够大 uwf
5!Z:>
@vL20O.
delete []p; //注意前面的[]号 &AVpLf:?
.:p2Tbo
p=NULL; f4-a?bp
E:zF/$tG
W?yd#j
十四、关于malloc/free 和new /delete ih,%i4<}6m
WwH+E]^e+
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 <IW#ME
IK,|5] *Ar
l 注意:malloc/free是库函数,new/delete是运算符 ] Z8Vj7~
dzK{
Z
l malloc/free不能执行构造函数与析构函数,而new/delete可以 DRqZ,[!+
-9RDr\&`(
l new/delete不能在C上运行,所以malloc/free不能被淘汰 C%*k.$#r!
} VJfJ/
l 两者都必须要成对使用 {3})=>u:S
X[#zCM
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 _&K
SN4Q))dAU
Hf'G8vW
十五、C++的特性 UnVm1ZWZ
q-nSLE+_;
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 q$1PG+-
gtUUsQ%y .
重载和内联:即可用于全局函数,也可用于类的成员函数; Kp+CH7I*
tiN?/
Const和Virtual:只可用于类的成员函数; qE'9QQ>:b
eC5 $#,HiC
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 R52I=
a5,*
]Jh+'RK\#
覆盖是指派生类函数覆盖基类函数 y_xnai
iU6Gp-<M,
函数名相同; ikE<=:pe
ih?^t(i
参数相同; `eu9dLzH
7'NwJ,$6\
基类函数必须有Virtual关键字; 4f(Kt,0
=^H4 Yck/5
不同的范围(派生类和基类)。 -hC,e/+
0%!rx{f#\
隐藏是指派生类屏蔽了基类的同名函数相同 4&/j|9=X
GUsl PnG
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 3\T2?w9u(
P/&]?f0/
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 7JSNYTH
]*7Y~dO
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 p4V eRJk%
i#%aTRKHd6
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 wP"dZagpj
]kG(G%r|M
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 lO2[JP
h*u`X>!!
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: Lg"C ]
gWY"w!f
将void Func(A a) 改为void Func(const A &a)。 lI>SUsQFfm
HHqwq.zIy
而void func(int a)就没必要改成void func(const int &a); Xl74@wq
OT'[:|x ;
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 Z$J#|
Zw
wqSyuGf
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 Fs[aa#v4B
BB|?1"neg
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; mDZ*E !B
ax
41N25
@3kKJ
十六、extern“C”有什么作用? ~}Rj$%_
Z4IgBn(Z_}
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 NWxUn.Gy9
[5Lz/ix=
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 q\H[am
^]
kF{
o?
^_lzZOhG
十七、构造函数与析构函数 vzmc}y G
Pb*5eXk
派生类的构造函数应在初始化表里调用基类的构造函数; E@Ad'_H
41SGWAd#:
派生类和基类的析构函数应加Virtual关键字。 n@ G[
H:"maS\I
不要小看构造函数和析构函数,其实编起来还是不容易。 d|4}obCt
d:yqj:
#include <iostream.h> 0T46sm r
J:skJ.Wx
class Base ~H!S,"n^,P
eilYA_FL.
{ &5:tn=E
O`vTnrY
public: S6[v;{xJ
SB)5@
nmS
virtual ~Base() { cout<< "~Base" << endl ; } @_z4tUP
Q?X>E3=U
}; Gm\/Y:U
-ig6w.%lk
class Derived : public Base a. z;t8
+o9":dl
{ 8n>9;D5n
XQS9,Hl
public: 2+X\}s1vN
?@V[#.
virtual ~Derived() { cout<< "~Derived" << endl ; } PiA0]>
7NJhRz`_
}; L5,NP5RC
HbW0wuI
void main(void) )wNP(
@$L
y '!m4-
{ p/h
Rk<K6
YY!Rz[/
Base * pB = new Derived; // upcast I(XOE$3
/i77
delete pB; Z4\=*ic@
)P+7PhE{J
} gg8Uo G
Hhh0T>gi
输出结果为: uS^Ipxe\
rvw)-=qR[
~Derived 0L/n ?bf
' MxrQ;|S
~Base #{\%rWnCm
O<V4HUW
如果析构函数不为虚,那么输出结果为 8e(\%bX
/~<@ *-'
~Base pfI"36]F
.p(T^ m2A*
,KFapz!
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 Ct>GYk$
{lc\,F* $
仿止该头文件被重复引用