一、#include “filename.h”和#include <filename.h>的区别 >fo &H_a
Q>}I@eyJ
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 ihH!"HH+
b]6;:Q!d
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 />\.zuAr&
J.":oD
6"
3!9JC
二、头文件的作用 ^~MHxF5d
(FMG W
(
加强安全检测 B!<{s'
R4}G@&Q
通过头文件可能方便地调用库功能,而不必关心其实现方式 nngL,-v#F
s@o"V >t
C%#C|X193
三、* , &修饰符的位置 Xu HJy
n*D)RiW
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 /eR @&!D '
LnZz=
~;m~)D
四、if语句 W5:S+
_?Jm.nT
不要将布尔变量与任何值进行比较,那会很容易出错的。 0y'34}
@tjC{?5Y
整形变量必须要有类型相同的值进行比较 \{?v|%n=/i
~"EkX
浮点变量最好少比点,就算要比也要有值进行限制 oG@P M+{
*goi^Xp
指针变量要和NULL进行比较,不要和布尔型和整形比较 I+O!<SB
vWfC!k-)b
WP^%[?S2
五、const和#define的比较 UDyvTfh1X
wSV[nK
const有数据类型,#define没有数据类型 _* 4
<
)#3,y6
个别编译器中const可以进行调试,#define不可以进行调试 TdD-#|5
!0Xes0gK0
在类中定义常量有两种方式 N!RyncJ
,`+y4Z6`W2
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; RW>Z~Nj
? dSrY
2、 用枚举代替const常量。 2%vwC]A
,O
a)
@uY%;%Pa8
六、C++函数中值的传递方式 M~N'z/
pS%,wjb&P
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) )Y?Hf2']
Xg!Mc<wA[
void fun(char c) //pass by value >YoK?e6
u#=N8
void fun(char *str) //pass by pointer IRo[|&c
0]>p|m9K^<
void fun(char &str) //pass by reference V^L;Nw5h
HdWghxz?)
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 =#%e'\)a
#3u8BLy$Q
函数的类型不能省略,就算没有也要加个void =K8`[iH
Q1eiU Y6
|7%$+g
七、函数体中的指针或引用常量不能被返回 Y!&dj95y
7\{<AM?*
Char *func(void) <#|3z8N2
x6Z$lhZ
{ %q>gwq
A
E? F @
char str[]=”Hello Word”; _rjCwo\
|k
4+I
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 >>^c_ 0"O
<\zb*e&vr
return str; , is
.{y
VdK-2O(.-
} r="X\ [on
AS;{O>}54
函数体内的指针变量并不会随着函数的消亡而自动释放 `m'2RNSc+#
?Cu#(
TqbKH08i/
八、一个内存拷贝函数的实现体 SKRD{MRsux
]s,T`
(&
void *memcpy(void *pvTo,const void *pvFrom,size_t size) OgH Wmb
d\Dxmb]o
{ 6oUT+^z#
5QmF0z)wR
assert((pvTo!=NULL)&&(pvFrom!=NULL)); "t_] Qu6
A;kAAM
byte *pbTo=(byte*)pvTo; //防止地址被改变 )_bXKYUX*0
>!WJ{M0
byte *pbFrom=(byte*)pvFrom; uF(-h~
pM
VeUK?
while (size-- >0) ;y k@`<
TR)'I
pbTo++ = pbForm++; 1YnDho;~
@~gz-l^$
return pvTo; C5sV-UMR
)SDGj;j+
} tO~H/0
[BV{=;iD
SxT:k,ji
九、内存的分配方式 Wdy2;a<\{
SZwfYY!ft0
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 0W=IuPDU
c yN_Sg
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 5jjJQ'
C t SAo\F
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 Vl9\&EL
yobi$mnsy!
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。
2EE#60
iwmXgsRa9}
L
YH9P-5H
十、内存分配的注意事项 >J8?n,*
J::SFu=
用new或malloc分配内存时,必须要对此指针赋初值。 q(uu;l[
QT-rb~
用delete 或free释放内存后,必须要将指针指向NULL @69q// #B
sHEISNj/^
不能修改指向常量的指针数据 d0N7aacY
yr;oq(&N
/D~
,X48+
十一、内容复制与比较 +pjD{S~Y
3d,|26I 7f
//数组…… H<FDi{
E|^a7-}|
char a[]=”Hello Word!”; 9'4cqR
~sA}.7
char b[10]; V25u'.'v
7z+NR&'M$
strcpy(b,a); X$st{@}ZB
a>Q7Qn
if (strcmp(a,b)==0) x3M`l|
i.byHz?/
{} }QC:!e,yG
/Hd\VI
//指针…… ?SQT;C3j(
cxmr|-^
char a[]=”Hello Word!”; oHa6fi
lv8tS -
char *p; bo@1c0
"kN5AeRg
p=new char[strlen(a)+1]; q+m&V#FT%
}S42.f.p
strcpy(p,a); 7v\OS-
+$<m ;@mZ
if (strcmp(p,a)==0) *?i~AXJm
h"<rW7z
{} *np%67=jO
i@g6%V=
lFRgyEPH
十二、sizeof的问题 kU#$
P|64wq{B8
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 0,VbB7 z
thq(tK7
char a[]=”Hello World!” %_/_klxnO
5B@&]-'~
char *p=a; D%BV83S
fC81(5
count<<sizeof(a)<<end; //12字节 \s)j0F)
4ci
@$nL1
count<<sizeof(p)<<endl; //4字节 ;,IGO7R
o!j? )0d
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 HF0J>Clq
cZHlW|$R
void fun(char a[1000]) K@?S0KMK
Z/2#h<zj
{ 6t@3
a?
Xf Y]qQP
count<<sizeof(a)<<endl; //输出4而不是1000 Z4rK$B
X+hyUz(%R
} Ejn19{
*VL-b8'A<
TT29LC@
十三、关于指针 %3~jg
X}S<MA`
1、 指针创建时必须被初始化 6rR}qV,+{
-1U]@s
2、 指针在free 或delete后必须置为NULL 1 "4AS_Q
2.2 s>?\
3、 指针的长度都为4字节 <ZCjQkka>r
$@DXS~UQA
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 %)]{*#N4
7MBz&wE^f
char *p=new char[100]; n.Ekpq\
$e0sa=/
strcpy(p,”Hello World”); AC
3 ;i
=G*<WcR
delete []p; //注意前面的[]号 [,lBY-Kz+
! 5 ]/2
p=NULL; MF>?! !
hGzj}t
W8d
5、数组指针的内容不能超过数组指针的最大容易。 H!7/U_AH
R{Cj]:Ky
如: zi<C5E`
XFH7jHnL+U
char *p=new char[5]; UXe @c@3
%/~Sq?f-9@
strcpy(p,”Hello World”); //报错 目标容易不够大 W${0#qq
Xi$uK-AHpj
delete []p; //注意前面的[]号 S{&;
_W&.{
7
p=NULL; (?oK+,v?L
+jQW 6k#
.p <!2
十四、关于malloc/free 和new /delete X(N!y"z
UKn>.,
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 Dy0RZF4_
i?||R|>;"'
l 注意:malloc/free是库函数,new/delete是运算符 joYj`K
7)<&,BWc
l malloc/free不能执行构造函数与析构函数,而new/delete可以
NouT~K`'
1[mX_ }K
l new/delete不能在C上运行,所以malloc/free不能被淘汰 v-g2k_o|
`Y8F}%i[
l 两者都必须要成对使用 q,kdr)-
!$Nh:(>:
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 ,uK
}$l
$M#G;W5c
X8y&|uH
十五、C++的特性 7oK!!Qd^w
?3"lI,!0
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 rVkRU5
Me2%X>;
重载和内联:即可用于全局函数,也可用于类的成员函数; ?>DN7je
{0QNqjue
Const和Virtual:只可用于类的成员函数;
mM!Gomp
=5',obYN>c
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 kpLDK81I
tVFl`Xr
覆盖是指派生类函数覆盖基类函数 J?LetyDNr]
o yK'h9Wt1
函数名相同; 3Vs8"BFjz
0.=dOz r
参数相同; M;-PrJdyt
7S}NV7
基类函数必须有Virtual关键字; g-Vxl|hR
d3<7t
不同的范围(派生类和基类)。 sA#}0>`3S
iTwb#Q=
隐藏是指派生类屏蔽了基类的同名函数相同 _?CyKk\I
K>N\U@@8i
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 0EKi?vP@y7
}k~ih?E^s
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 ;M1# M:
+9<"Y6
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 eD4X:^@
W 2&o'(P\
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 n#|ljC
wQEsq<
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 d)1 d0ES
SFv'qDA
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: 3 f@@|vZF
|6v
$!wBi
将void Func(A a) 改为void Func(const A &a)。 A+de;&
@>cz$##`
而void func(int a)就没必要改成void func(const int &a); UQc!"D
FC@h6\+a
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 ?(0=+o(`
qILb>#
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 C3)*Mn3%P
xhK8Q
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; [MhKR }a
+saXN6
;-#2p^
十六、extern“C”有什么作用? G5vp(%j
FUzN}"\1
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 t-B5,,`
~@ =(#tO.
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 n+MWny
+fS<YT
<-;/,uu
十七、构造函数与析构函数 ,cE yV74
`,QcOkvbC
派生类的构造函数应在初始化表里调用基类的构造函数; _t&`T
%e^GfZ
派生类和基类的析构函数应加Virtual关键字。 =gNPS0H
n&OM~Vs
不要小看构造函数和析构函数,其实编起来还是不容易。 '.EO+1{a
%
bfe_k(
#include <iostream.h> d^MRu#]
J?{@pA
class Base _Ne fzZWUJ
:aQ.:b(n
{ Rjp7H
~(nc<M[
public: 76H>ST@G|
>Q$ph=
virtual ~Base() { cout<< "~Base" << endl ; } |;:g7eb
V56WgOBxz
}; ls7eypKR
JTIt!E}P
class Derived : public Base Ps!umV
TZ&X0x8
{ 6_,JW{#"
0civXZgj
public: Y<L35
?
w=pr?jt1:
virtual ~Derived() { cout<< "~Derived" << endl ; } 'X<4";$mU
m8@&-,T
}; !iO2yp
$Nd,6w*`
void main(void)
?iZ2sRWR6
mG"xo^1_H
{ %UAF~2]g
FA%_jM
Base * pB = new Derived; // upcast E\|nP~;~F9
o]EL=j
delete pB; KL9k9|!p
fIl;qGz85
} WQ{[q" O
`78Bv>[A
输出结果为: ~)^'5^
;z.L^V0
~Derived oNZ_7tU
d]poUN~x
~Base h5SJVa
q.p.$)
如果析构函数不为虚,那么输出结果为 ,jOJ\WXP
8[;vC$
~Base ,DZvBS
v\GVy[Qyv
H4s~=iB
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 gVrQAcJj
J$Z=`=]t+
仿止该头文件被重复引用