一、#include “filename.h”和#include <filename.h>的区别 XpU%09K
ud,=O Xq
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 Y+0HC2(o
65||]l
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 WXX)_L$2
/7[X_)OG
KR sY `[Y
二、头文件的作用 g;G]Xi.B}
}6!*H!
加强安全检测 40)Ti
4fa2_
通过头文件可能方便地调用库功能,而不必关心其实现方式 w_lN[u-L
_@:O&G2nB
P!K;`4Ika
三、* , &修饰符的位置 W2W4w
.1#G*A|
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 Z %\*\6L)
-J\R}9 lIm
qVMBZ\`Qm
四、if语句 bL9vjD'}
L>.*^]
不要将布尔变量与任何值进行比较,那会很容易出错的。 *Y/}EX!F
7t~12m8x
整形变量必须要有类型相同的值进行比较 LOf)D7T
W5_aS2$
浮点变量最好少比点,就算要比也要有值进行限制 VYC$Q;Z
@^UnrKSd
指针变量要和NULL进行比较,不要和布尔型和整形比较 l11+sqg
$>=?'wr
CZ4Nw]dtR
五、const和#define的比较 a15kFun
,J)wn;@
const有数据类型,#define没有数据类型 aq-R#q
,3~[cE<4
个别编译器中const可以进行调试,#define不可以进行调试 ?|,-Bft3
~![J~CkPS
在类中定义常量有两种方式 FvVR \a
N~t4qlC/
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; w_h}c$;GK
CPt62j8
2、 用枚举代替const常量。 1b4/
$zv&MD!&h
nTQ&nu!
六、C++函数中值的传递方式 0AWOdd>.
rIJv(&l
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) :j}4F
`#x}-A$
void fun(char c) //pass by value vnOl-`Z ~
WO]9\"|y
void fun(char *str) //pass by pointer AaX][2y8
)o%sN'U,1
void fun(char &str) //pass by reference ;r.0=Uo9]
DL]\dD
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 |';oIYs|$
(dgBI}Za
函数的类型不能省略,就算没有也要加个void 2=V~n)'a
$$f89, h
5eJMu=UpR
七、函数体中的指针或引用常量不能被返回 09L"~:rg
Q$XNs%7w5,
Char *func(void) (N
0kTi]b
gof'NT\c
{ 7x5wT ?2W
JNk6:j&Pf
char str[]=”Hello Word”; *iwVB^^$
ILyI%DA &
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉
q-|j
=
=s5g9n+7
return str; ;VW->ia6
;V)jC
} $3c9iVK~_
o7=#ye&P
函数体内的指针变量并不会随着函数的消亡而自动释放 aTU[H~dTU
R?L?6~/q
7+;$_,Xo<
八、一个内存拷贝函数的实现体 fjP(r+[
Y~"5HP|
void *memcpy(void *pvTo,const void *pvFrom,size_t size) c[<>e#s+;
8o%g2 P9.
{ rGIf/=G^r
$z48~nu@j
assert((pvTo!=NULL)&&(pvFrom!=NULL)); TkyP_*
XS oHh-
byte *pbTo=(byte*)pvTo; //防止地址被改变 Kd;Iu\4hv
Iy8fN"I9D
byte *pbFrom=(byte*)pvFrom; N.D7
^<OcbOn;O
while (size-- >0) .4O~a
"HwSW4a]
pbTo++ = pbForm++; 5 ^867
7I4<Dj
return pvTo; UEeq@ot/ 4
(mOL<h[)IP
} 4];<`
%
,d`6
{ll
YHQvx_0yP
九、内存的分配方式 tRu j}n+x
Uy98lv
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 @t{`KB+
^
"OWW -m
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 -|g9__|@
)kk10AZV-E
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 #w6ty<b;
Hzc5BC
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 6tZ ak1=V
64LAZEQX
[~{'"-3L0
十、内存分配的注意事项 ;m#_Rj6
?mn&b G
用new或malloc分配内存时,必须要对此指针赋初值。 57(5+Zme
=lZtI6tZ
用delete 或free释放内存后,必须要将指针指向NULL x +]ek
=Vat2'>+
不能修改指向常量的指针数据 /mG-g%gE
u?7^+z
Y?#aUQc
十一、内容复制与比较 vTsMq>%,<
Ou7nk:I@
//数组…… GFTOP%Tgl
8Ao-m38
char a[]=”Hello Word!”; ;q&uk-
U
uEm{
char b[10]; Dt:NBN
Iq@&?,W
strcpy(b,a); KD^n7+w%
@fh:lsw
if (strcmp(a,b)==0) LMHiiOs,
~+S,`8-P
{} DI0Wk^ m
Pe/8=+qO
//指针…… 6lob&+
?M BOd9
char a[]=”Hello Word!”; AwtiV-w
`R
m<1
char *p;
Xf{ht%b
\OE,(9T2P.
p=new char[strlen(a)+1]; p1!-|Sqq
e:+[}I)
strcpy(p,a); !uW;Ea?
aJLc&o 8Yg
if (strcmp(p,a)==0) ~B\O{5W
%;,4q B
{} 7* R
%zJ
fLg
:+Ue<B
;Iax \rQ
十二、sizeof的问题 .2V?G]u
?h)T\z
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 WP5Vev9*+
e(H{C
char a[]=”Hello World!” X:m m<4
oer3DD(
char *p=a; I(uM`g
4w#:?Y
_\[
count<<sizeof(a)<<end; //12字节 1Vx>\A
e/b
|
sl
count<<sizeof(p)<<endl; //4字节 vD76IG j m
8lFYk`|g
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 {[~dI ~
G *
=>
void fun(char a[1000]) sL)7MtNwy
"EBCf.3-
{ Q9k;PJ`@
^VsE2CX
count<<sizeof(a)<<endl; //输出4而不是1000 WDJ rN
4}-G<7*
} m:Fdgu9
lUIh0%O
sspGB>h8l
十三、关于指针 y7vA[us
4m!w<c0NL
1、 指针创建时必须被初始化 } 8[
/^$n&gI
2、 指针在free 或delete后必须置为NULL PQ 2rNY6
a
y$CUw
3、 指针的长度都为4字节 pfQ3Y$z
YBL.R;^v
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 w1LZ\nA<
g>QN9v})
char *p=new char[100]; w[g`)8Ib
e)$a ;6
strcpy(p,”Hello World”); _wUg+Xs]
K0|:+s@u
delete []p; //注意前面的[]号 Uf9L*Z'6il
#xw3a<z ?u
p=NULL; X*M2 O%g`L
{Ga=;0
5、数组指针的内容不能超过数组指针的最大容易。 nd"$gi
VNwOD-b/]
如: P6A##z
qwq5yt?
char *p=new char[5]; Fg0!2MKq*
d^8n
strcpy(p,”Hello World”); //报错 目标容易不够大 NInZ~4:
:xk+`` T
delete []p; //注意前面的[]号 r-No\u_
piFZu/~Gq\
p=NULL; 8WpZ"
@w(X}q1
=7F?'&LC
十四、关于malloc/free 和new /delete p@ U[fv8u
]U&<y8Q_6
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 '4}8WYKQ
+1^L35\@
l 注意:malloc/free是库函数,new/delete是运算符 y?Pw6;e.
{a]u
l malloc/free不能执行构造函数与析构函数,而new/delete可以 O7m-_#/\
EFv^uve
l new/delete不能在C上运行,所以malloc/free不能被淘汰 y"k%Wa`*
yIg^iZD
l 两者都必须要成对使用 G +AP."M?
:mhO/Bx
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 N]-skz<v
>z73uKA(
R&Ss ET.
十五、C++的特性 <{i1/"k?X
Js^(mRv=
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 Zr(eH2}0D
eQ*zi9na
重载和内联:即可用于全局函数,也可用于类的成员函数; gHFQs](G.
3R%yKa#
Const和Virtual:只可用于类的成员函数; i:Gyi([C
~=9S AJr]
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 Qe_C^(P
rONz*ly|i
覆盖是指派生类函数覆盖基类函数 WLiF D.
N*+WGsxl$z
函数名相同; |Xt6`~iC
_na/&J6
参数相同; |l@z7R+4*
WM7LCP
基类函数必须有Virtual关键字; *JAC+<~d
GI>(S
不同的范围(派生类和基类)。 [=cYsW%WG
Awr(}){
隐藏是指派生类屏蔽了基类的同名函数相同 @"H7Q1Hg!*
7~);,#[ky
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 Eqi;m,)
pG22Nx
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 JvNd'u)Z<
3p]\l ]=
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 /qFY$vj
= ?BhtW
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 6 X'#F,M
">MsV/
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 G cB<i
Zu4au<
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: KGc!#C
cj[x%eK>
将void Func(A a) 改为void Func(const A &a)。 NKTy!zWh
w`v`aw]
而void func(int a)就没必要改成void func(const int &a); lbPn<
"&o"6ra}
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 dnV&U%fO
q=*bcDu
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 pfw`<*e'
/1_O5'5+v
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; wPq9`9 #
.hUlI3z9
,3!TyQ\m'
十六、extern“C”有什么作用? %Y,Ru)5}
8l'W[6
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 q>wO=qWx
U.h2 (-p
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 =uEpeL~d;+
2vhP'?;K
HD3WsIim*
十七、构造函数与析构函数 Z!*6;[]SfG
~NLthZ(O
派生类的构造函数应在初始化表里调用基类的构造函数; ?zfm"o
KK{_s=t%<
派生类和基类的析构函数应加Virtual关键字。 lM#,i\8Q
s3 fQGbU
不要小看构造函数和析构函数,其实编起来还是不容易。 aX*9T8H/
X&i;WI
#include <iostream.h> PjXiYc&
OUFy=5(%:
class Base G6lC[eK
Xk1uCVUe5
{ #l@P}sHXq
'z{|#zd9
public: w#ZzmO
sLFZ61rT
virtual ~Base() { cout<< "~Base" << endl ; } M8$eMS1
lBm`W]3T
}; 3,2$Ny3N
w'XN<RWA
class Derived : public Base j\zlp
r^H,H'BohJ
{ /^v!B`A@
unKl5A[h
public: !\'H{,G
:{VXDT"
virtual ~Derived() { cout<< "~Derived" << endl ; } i7cUp3
*e<}hmDr
}; Uq`6VpZ
_+Sf+ta
void main(void) X|G[Ma?
2-jXj9kp`
{ f~ /hsp~Hp
%*o
Base * pB = new Derived; // upcast &5XEjY>@
2 |JEGyDS-
delete pB; +H *6:
587;2
} #Ma:Av/
)
!0P:G#o-$
输出结果为: w%..*+P
JYmYX-
~Derived '.<c[Mp
cd=|P?Bi
~Base g'{?j~g
Ryh 0r
如果析构函数不为虚,那么输出结果为 (:O6sTx-hE
<&g