一、#include “filename.h”和#include <filename.h>的区别 >V1vw7Pa
orBB5JJ
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 [QUaC3l)
k6eh$*!
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 [~_)]"pU
.Nk'yow
7]sRHX0o%
二、头文件的作用 `4IZ4sPi
/ vgEDw
加强安全检测 }Um,wY[tK
f[1 s4Dp3-
通过头文件可能方便地调用库功能,而不必关心其实现方式 9!} ?}`'_
"xWrYq'"
!U::kr=t
三、* , &修饰符的位置 y[`>,?ns5
gug9cmA/Q7
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 _ \&vA5-
NW]zMU{c
'k'"+
四、if语句 <cm(QNdcC
GY`mF1b
不要将布尔变量与任何值进行比较,那会很容易出错的。 /tdRUX
iy!SqC
整形变量必须要有类型相同的值进行比较 ]?S@g'Jd0Q
fM/~k>wl
浮点变量最好少比点,就算要比也要有值进行限制 Ql#y7HW
/aV;EkyO,
指针变量要和NULL进行比较,不要和布尔型和整形比较 5]f6YlJZ
R<djW5 ()f
i 1dE.f;
五、const和#define的比较 8yCt(ms
s@02?+/
const有数据类型,#define没有数据类型 MoZ8A6e?B
QJ\+u
个别编译器中const可以进行调试,#define不可以进行调试 Z1}@N/>>
iWGn4p'
在类中定义常量有两种方式 o[^nmHrM2
~V t?'v20@
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; %fuV]
3QI. |;X
2、 用枚举代替const常量。 F:7d}Jx
43.Q);4
jhR`%aH4
六、C++函数中值的传递方式 >\?RYy,s$
\X2r?
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) icK>|
J5!-<oJ/
void fun(char c) //pass by value rSa=NpFxLu
FW"n+7T
void fun(char *str) //pass by pointer Nn#;Kjul.
<EKTFHJ!
void fun(char &str) //pass by reference U3**x5F_
v?Zo5uVoq
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 DuQW?9^232
{h*)|J
函数的类型不能省略,就算没有也要加个void Y'y
yrn}
8|L;y[v
#HDP ha
七、函数体中的指针或引用常量不能被返回 0^3n#7m;K
RNo~}#
Char *func(void) QQ,V35Vp[
+mPVI
{ 6Vgxfic
7v&>d,
char str[]=”Hello Word”; zx/$
FLo`EE":O(
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 ]T<tkvcI
M3G ecjR
return str; ;w7s>(ITZ
h_HPmh5
} {TXfi'\
yUjkRT&h
函数体内的指针变量并不会随着函数的消亡而自动释放 (u4'*[o\t
7NvnCs
3a?|}zr4
八、一个内存拷贝函数的实现体 '=0l{hv@
R=2"5Hy=
void *memcpy(void *pvTo,const void *pvFrom,size_t size) esM r@Oc
x7xMSy
{ .uinv
!]3kFWs
assert((pvTo!=NULL)&&(pvFrom!=NULL)); MTip4L W9
cT5BBR
byte *pbTo=(byte*)pvTo; //防止地址被改变 bkuJN%
^[&,MQU{7
byte *pbFrom=(byte*)pvFrom; e I9#JM|2
bcgXpP
while (size-- >0) l(9AwVoAR|
]D&U}n
pbTo++ = pbForm++; Ft^X[5G4L
Jcy+(7lE)
return pvTo; fg7
7|xu)zYB
} Zts1BWL[
1N[9\Yi
Y(u`K=*
九、内存的分配方式 )Ma/]eZ^I
*xjP^y":
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 .}5qi;CA
~h:(9q8NLC
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 BNgm+1?L
F`La_]f?b\
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 |- <72$j
T`bUBrK6g`
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 E{P94Phv
OdpHF~(Y/
7p-
RPC
十、内存分配的注意事项 -'F27])
,D'm#Fti
用new或malloc分配内存时,必须要对此指针赋初值。 .D;6
r4S
9}_'
用delete 或free释放内存后,必须要将指针指向NULL i;atYltEJ2
)HcLpoEi
不能修改指向常量的指针数据 FTr'I82m(
W^7yh&@lU
&>!-67
十一、内容复制与比较 f@gvDo]Y
b0/YX@
//数组…… @?jtB
~0h@p4
char a[]=”Hello Word!”;
2OpkRFFa
Be9,m!on
char b[10]; G`;\"9t5h
m[z$y
strcpy(b,a); c39j|/!;Y
B<ncOe
if (strcmp(a,b)==0) Y/5(BK)
vN:!{)~z
{} $o0.oY#
IT7],pM
//指针……
peHjKK
i&8|@CACb
char a[]=”Hello Word!”; `kE7PXqa
w+r).PS}C
char *p; D2GF4%|
1]9w9!j
p=new char[strlen(a)+1]; 3IJ0 P.x!o
f5p/cUzX
strcpy(p,a); cU-A1W
C_'EO<w$
if (strcmp(p,a)==0) E[7E%^:Mg
XUKlgl!+.
{} >28l9U
"h #/b}/
w3 kkam"
十二、sizeof的问题 vaJl}^T
^BM !TQ%!
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 TtF+~K
PxQQf I>
char a[]=”Hello World!” &CcW(-
]Y-Y.&b7t
char *p=a; {bADMj1
}n
"5r(*^@
count<<sizeof(a)<<end; //12字节 SQhVdYU1'
7r50y>
count<<sizeof(p)<<endl; //4字节 {6WG
Zk/ejhy0
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 `N&*+!O%
^{{a
v?h
void fun(char a[1000]) LR{bNV[i
Te[v+jgLY,
{ W/%hS)75
[& Z-
*a
count<<sizeof(a)<<endl; //输出4而不是1000 7{(UiQbf
] jY^*o[
} .k-6LR
5eE\
X /
kG{};Vm
十三、关于指针 x=IZ0@p
7#d:TXS
1、 指针创建时必须被初始化 wJ pb$;
/a<UKh:A[
2、 指针在free 或delete后必须置为NULL Kc95yt
7y&6q`y E
3、 指针的长度都为4字节 Jfk#E^1
.drY
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 FZO&r60$E
iCA-X\E
char *p=new char[100]; N$=9R
c|JQ0] K
strcpy(p,”Hello World”); NmXRA(m
s9a`2Wm
delete []p; //注意前面的[]号 h=,hYz?]
%#rtNDi
p=NULL; 7K
"1^
|!9xL*A
5、数组指针的内容不能超过数组指针的最大容易。 bS2g4]$'po
FZn1$_Svr
如:
?ueL'4Mm
ju'aUzn
char *p=new char[5]; ]hS<"=oj
>zDQt7+g;
strcpy(p,”Hello World”); //报错 目标容易不够大 *;9H \%
vanV |O
delete []p; //注意前面的[]号 VBQAkl?(}4
l"(PP3
p=NULL; ;y. ;U#O
br
Iz8]
l?2
十四、关于malloc/free 和new /delete i+qg*o$
=1dczJHV
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 05k'TqT{c
Im\ ~x~{
l 注意:malloc/free是库函数,new/delete是运算符 dQ7iieT
wM4{\ f\
l malloc/free不能执行构造函数与析构函数,而new/delete可以 Tx~w(A4:
|'1.ajxw
l new/delete不能在C上运行,所以malloc/free不能被淘汰 Jz>P[LcB
7Y[ q)lv
l 两者都必须要成对使用 ]W$G!(3A
B*mZxY1
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 rh1PpsSc
Qw5(5W[L
\1gAWUt('
十五、C++的特性 _hyqHvP
9#9bm
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 v0dzM/?*
)I3E
重载和内联:即可用于全局函数,也可用于类的成员函数; MKvmzLh$)
/KWdIP#
Const和Virtual:只可用于类的成员函数; Nwt[)\W `
?wPTe^Qtv
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 #7Q9^rG
D.:`]W|
覆盖是指派生类函数覆盖基类函数 s|H7;.3gp
&"JC8
函数名相同; ^7/v[J<<
jvsSP?]n
参数相同; Be]z @E1x
[n| }>
基类函数必须有Virtual关键字; lY"l6.c
U`=r.>
不同的范围(派生类和基类)。 ed/B.SY
hBX.GFnw
隐藏是指派生类屏蔽了基类的同名函数相同 gEsD7]o(=
?_d>-NC
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 %;h1n6=v2
s=-?kcoJ2d
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 J)B3o$
rhQ+ylt8I
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 o.NU"$\?
&4|]VOf
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 hG.}>(VV
Q2Ey RFT
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 ?OF$J|h
1="]'!2Is
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: fqbeO 9x
VnSO>O
将void Func(A a) 改为void Func(const A &a)。 9)]`le
zeQ~'ao<
而void func(int a)就没必要改成void func(const int &a); [&*irk
g]HWaFjc5
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 T88$sD.2
'
]^.`}Y=`g
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 *~6]IWN`
.wd7^wI^S
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; %A~. NNbS
2= ;ZJ
u`Nrg<
十六、extern“C”有什么作用? ";(m,if-
>S`=~4
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 @HMH>;haE
*(q{k%/M
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 paD[4L?4Hk
fgtwVji
aC1 xt(
十七、构造函数与析构函数 89D`!`Ah]
M5+R8ttc
派生类的构造函数应在初始化表里调用基类的构造函数; /];N 1
:RB7#v={
派生类和基类的析构函数应加Virtual关键字。 9-m_
e=jk6
/G7^ l>pa
不要小看构造函数和析构函数,其实编起来还是不容易。 J+ :3==,
I:=!,4S;
#include <iostream.h> ]wV\=m?z&
;:[P/eg
class Base ?^!J:D?
g~K-'Nw
{ bt=D<YZk
mD +9/O!
public: _?{KTgJ G
~oSA&v4V
virtual ~Base() { cout<< "~Base" << endl ; } CpN*1s})d
adoK-bS t
}; YGChVROG~
D&mPYxXL
class Derived : public Base Q_,!(N
: ciwh
{ -M]/Xv]
!lEV^SQJs
public: qfFa" a
EMH-[EBx
virtual ~Derived() { cout<< "~Derived" << endl ; } EiM\`"o
w\d1
}; 0W6='7
79)iv+nf\l
void main(void) Dy. |bUB!f
}W " i{s/
{ B\AyG4J
r\b$/:y<e
Base * pB = new Derived; // upcast P!9-!+F"
J^` pE^S
delete pB; )06. dZq\
L~|_)4
} .ejC#vB{KM
l3MA&&++KF
输出结果为: 2g)q
(
Sb?v5
~Derived K~UT@,CS60
iuEe#B;!
~Base PB8U+
k~<ORnda
如果析构函数不为虚,那么输出结果为 L-|7
&
<Vyl*a{%
~Base p0Ij4
'#lEUlB
t2.]v><