一、#include “filename.h”和#include <filename.h>的区别
" V`MNZ
v+*l|!v
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 $'Hg}|53
TGz5t$]I
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 Up$vBE8i]
k]`3if5>
[]M+(8Z_P
二、头文件的作用 uv[e0,@
G#4cWn'
加强安全检测 `&U ['_%
gU}?Yy
通过头文件可能方便地调用库功能,而不必关心其实现方式 T<0Bq"'%
rLcQG
.W&rcqy
三、* , &修饰符的位置 <ZNa`
m H'jr$ ?
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 STmCj
+:[dviyPt
ca_8S8lv
四、if语句 UmU=3et<Wj
y*6r&989
不要将布尔变量与任何值进行比较,那会很容易出错的。 :L FwJ
|C S[>0mV!
整形变量必须要有类型相同的值进行比较 <u"#Jw/VP
yREO;m|o
浮点变量最好少比点,就算要比也要有值进行限制 n6nwda
c"J(? 1O
指针变量要和NULL进行比较,不要和布尔型和整形比较 XI,F^K
qD4e] 5
^dP@QMly6
五、const和#define的比较 R#bg{|
o=_4v^
const有数据类型,#define没有数据类型 <..%@]+
f|FQd3o)
个别编译器中const可以进行调试,#define不可以进行调试 _wf"E(c3D
9bXU!l[
在类中定义常量有两种方式 |P2GL3NR
^ :Q |,oy
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; "O|fX\}5
$(}kau
2、 用枚举代替const常量。 Y^S0K'N
(w% hz']
cuquA ~
六、C++函数中值的传递方式 vVLR9"rHM
mI in'M
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) cVn7jxf
~%Yh`c
EP
void fun(char c) //pass by value Z[`J'}?|
BoIe<{X(9
void fun(char *str) //pass by pointer 7XWgY%G
uW[s?
void fun(char &str) //pass by reference {M E|7TS=
miHW1h[=
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 VkhK2
[;5HI'px
函数的类型不能省略,就算没有也要加个void n*iaNaU"'
M7,|+W/RK
sS(^7GARa
七、函数体中的指针或引用常量不能被返回 =GM!M@~,Ab
3g2t{%
Char *func(void) ZLKS4
<WBGPzVZE
{ 8gBqur{
+I\bs.84
char str[]=”Hello Word”; S_2I8G^A
e@^}y4
C
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 uNhAfZ
ZVIBmx
return str; iJrscy-
o
ohf))
} B{1+0k
6x/ X8zu
函数体内的指针变量并不会随着函数的消亡而自动释放 9f,HjRP
E4y"$U%.
#^#)OQq]
八、一个内存拷贝函数的实现体 |Be.r{l
s9`T% pg
void *memcpy(void *pvTo,const void *pvFrom,size_t size) NK#Dq&W+&
`(B1 "qRi
{ a/)TJv
u{p\8v%7
assert((pvTo!=NULL)&&(pvFrom!=NULL)); `O}.
.N]g
<6L$:vT_
byte *pbTo=(byte*)pvTo; //防止地址被改变 N{p2@_fnB
vW)GUAF[
byte *pbFrom=(byte*)pvFrom; p6}jCGJ
oS,<2Z
while (size-- >0) ,}FYY66K
NKd@Kp`,
pbTo++ = pbForm++; PL+fLCk,I
={L:q8v)
return pvTo; `8'T*KU
Ha
C?,
} )If[pw@j
ir,Zc\C
BTd'bD~EA
九、内存的分配方式 LK:|~UV?
[Q 2t,tQx
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 Vj?.' (
GF/p|I D
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 KP<J~+_ik
wH${q@z _
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 F~l3?3ZV
IG9Q~7@
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 ([9h.M6v
SV\x2^Ea0
]7u8m[@
十、内存分配的注意事项 g:o\ r
(
nev*TYY?A
用new或malloc分配内存时,必须要对此指针赋初值。 }lxvXVc{I
Bnxzy
n
用delete 或free释放内存后,必须要将指针指向NULL ReK@~#hLY
)7i?8XiSZF
不能修改指向常量的指针数据 ?Y hua9
D 1hKjB&
+qz)KtJS
十一、内容复制与比较 dIpt&nH&$
'Vrev8D
//数组…… rf`Br\g8
nL:vRJr-$
char a[]=”Hello Word!”; &%*S
MW4dPoa
char b[10]; } 1XLe
j{;3+LCo*
strcpy(b,a); ?&GMp[
f^%E]ki
if (strcmp(a,b)==0) -91l"sI
y2qESAZ%k}
{} SY$%!!
@R
cLYc""=
//指针…… 3,F/i+@
VG8rd'Z
char a[]=”Hello Word!”; !}3`Pl.(r
yav)mO~QU6
char *p; y\S7oD(OR
/ P:Hfq
p=new char[strlen(a)+1]; FI/YJ@21
zhCI+u4/qz
strcpy(p,a); )-QNWN
H
4KM$QHS5{
if (strcmp(p,a)==0) iP!Y4F
G/8xS=
{} 9Y 4N
asq/_`
{&<}*4D
十二、sizeof的问题 k0YsAa#6V
~o%-\^oc
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 O)5PUyC:H
3w9
]@kU
char a[]=”Hello World!” sTA/2d
=3zn
Ta }
char *p=a; K?;p:
'0O[ dN
count<<sizeof(a)<<end; //12字节 L$Leo6<3a
]8_h9ziz
count<<sizeof(p)<<endl; //4字节 z\E"={P&
\=@r1[d
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 RYV6hp)|
V%0.%/<#5
void fun(char a[1000]) rgYuF,BT.
$HXB !$d
{ 28)TXRr-
b"Mq7&cf
count<<sizeof(a)<<endl; //输出4而不是1000 #VOjnc/rW
(wlsn6h
} g_>ZE
:HE]P)wz-
`;_tt_
十三、关于指针 t@u\ 4bv
cV{ZDq
1、 指针创建时必须被初始化 `HM3YC
pNqf2CnnT
2、 指针在free 或delete后必须置为NULL ft'iv
,SyUr/D
3、 指针的长度都为4字节 Fkz
B@;)$1-UT
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 YEQW:r_h.S
&CL|q+-
char *p=new char[100]; ZM vTDH!
[[e |GQ
strcpy(p,”Hello World”); -/-6Td1JY>
4v|/+J6G
delete []p; //注意前面的[]号 Ke ?uE
?:?4rIZ<
p=NULL; }K>HS\e
2*citB{
5、数组指针的内容不能超过数组指针的最大容易。 p0rwiBC=q
@1F 'V'
如: ^)q2\YE;
O$Vm#|$sq
char *p=new char[5]; 30_un
MA+-2pMc|7
strcpy(p,”Hello World”); //报错 目标容易不够大 ;-?ZI$
{}pqxouE
delete []p; //注意前面的[]号 kppRQ Q*[
&'7"i~pC
p=NULL; ~+#--BhV
pIu H*4Vz
uit-Q5@~
十四、关于malloc/free 和new /delete UNQRtR/
w`}9/s;$
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 s1vrzze
Z)
Xs;7
l 注意:malloc/free是库函数,new/delete是运算符 M_1Tx
e_=pspnZ
l malloc/free不能执行构造函数与析构函数,而new/delete可以 zcB2[eaV
b.4Xn0-M
l new/delete不能在C上运行,所以malloc/free不能被淘汰 "rGOw'!q>
y<`?@(0$
l 两者都必须要成对使用 q.MVF]
?4ILl>*
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 M%{?\)s
>J}n@MZ
5!ubY
6Ph
十五、C++的特性 HJ qQlEq
z"K(
bw6
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 q{GSsDo-:V
JYd7@Msfc
重载和内联:即可用于全局函数,也可用于类的成员函数; b;L>%;
b!]0mXU
Const和Virtual:只可用于类的成员函数; s$Zq/l$1x
*e<Eu>fW#&
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 fcICFReyV
z8[H:W#G
覆盖是指派生类函数覆盖基类函数 <{/;1Dru
ch>Vv"G>
函数名相同; lV<Tsk'
20VVOnDY
参数相同; Lq-33#n/
oM<!I0"gC+
基类函数必须有Virtual关键字; A*;?U2
_E6}XNS
不同的范围(派生类和基类)。 o}=.
ufCqvv>'
隐藏是指派生类屏蔽了基类的同名函数相同 u:k:C
Mjj}E
>&
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 y-#
"XNu-_$N<a
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 =#(0)p$EC
i~)NQmH<
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 Px?Ao0)Z,
'qV3O+@MF
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 ADGnBYE
&|N%#pYS
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 %X9b=%'+
\V^*44+
<!
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: jJVT_8J
C.>
将void Func(A a) 改为void Func(const A &a)。 i<m$#6<Z
+~d1;0l|
而void func(int a)就没必要改成void func(const int &a); |qlS6Aln
x=5P+_
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 e8WEz
4r_
kT^*>=1
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 ku9@&W+
nlzW.OLM
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; {/d4PI7)tK
2@ 9pr
gF[6c`-s
十六、extern“C”有什么作用? hr$Sa
VLsh=v
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 >5;N64]!)
sEce{"VC
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 rH_Jh}Y
`c"4PU^
g5#CN:%f
十七、构造函数与析构函数 [ -ISR7D
B0oxCc/'sZ
派生类的构造函数应在初始化表里调用基类的构造函数; b~_B
[cf
$!G` D=
派生类和基类的析构函数应加Virtual关键字。 bj@xqAGl
vv+D*e&<
不要小看构造函数和析构函数,其实编起来还是不容易。 *hVb5CS
BeK2;[5C
#include <iostream.h> Ge~q3"
k-"<{V
class Base ]9jZndgC
__!m*!sd
{ Y@Y`gF6F
Ic'Q5kfM
public: R]u
(l+`
lv4(4$T
virtual ~Base() { cout<< "~Base" << endl ; } ]cIu|bRO
|q;Al
z{
}; 7*i}km
G0}Dq MTi
class Derived : public Base eC ~jgB
U98_M)-%&
{ ->\N_|_
Ap%O~wA'
public: fk>l{W}e)
Dl%?OG<
virtual ~Derived() { cout<< "~Derived" << endl ; } 9x=3W?K:,
S'o ]=&
}; R<_?W#$j
0q{[\51*
void main(void) OX+hZ<y
`<^*jB@P
{ ic-IN~J-
W,3zL.qH"
Base * pB = new Derived; // upcast o(qEkR:4kd
/xySwSmh3
delete pB; 3 > |uF
-Q$b7*"z(
} -#aZF2z
'M8aW!~
输出结果为: O)uOUB
EJLQ&oH[
~Derived (SF1y/g@=
Z:@6Lv?CN
~Base _gW{gLYyJ
K\P!a@>1
如果析构函数不为虚,那么输出结果为 ~:[!Uyp0b
Seda }
~Base :a.0hes
$n-Af0tK
0z`/Hn
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 mb\h^cKaq
txq~+'A:+
仿止该头文件被重复引用