一、#include “filename.h”和#include <filename.h>的区别 ?-^eI!
20[_eu)
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 b&k !DeE
&A=>x
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 i7h!,vaK
6FMW}*6<
x!CCSM;q
二、头文件的作用 ?yKW^,q+
_yje"
加强安全检测 Y8I*B=7
NABwtx>.
通过头文件可能方便地调用库功能,而不必关心其实现方式 YJZViic
IY$H M3t7
"b&[W$e
三、* , &修饰符的位置 G(7!3a+
K07b#`NF6
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 JTu^p]os?
3Qt-%=b&
v=4,kG
四、if语句 iN\D`9e
?`PG`|2~
不要将布尔变量与任何值进行比较,那会很容易出错的。 CBC0X}_`
r|rOIAo
整形变量必须要有类型相同的值进行比较 qaK9E@l
BU|=`Kb|))
浮点变量最好少比点,就算要比也要有值进行限制 ?#|Y'%a"
M7R.?nk
指针变量要和NULL进行比较,不要和布尔型和整形比较 J!sIxwF
'bN\8t\S
BbA7X
五、const和#define的比较 B4k~~ ;|
x:bJ1%
const有数据类型,#define没有数据类型 o"F=3b~:n
1`1U'ibhe
个别编译器中const可以进行调试,#define不可以进行调试 H.sHXuu
JTuU}nm+
在类中定义常量有两种方式 {"<D$*K~
vu^ '+ky
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; 9pN},F91n:
.
IBy'
2、 用枚举代替const常量。 Ii"h:GY;\
)l}Gwd]h
8^26g3
六、C++函数中值的传递方式 PPiN`GM
}EB/1 8
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) sqkk4w1#C
uveby:dh
void fun(char c) //pass by value U_ j\UQC
Hk'D@(hS
void fun(char *str) //pass by pointer p<#WueR[
5 rpX"(
void fun(char &str) //pass by reference feOX]g#
qx3@]9
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 $[5S M>e]
&)?ECj0`
函数的类型不能省略,就算没有也要加个void 2y/|/IW=
eh=.Q<N
HyKvDJ
3_
七、函数体中的指针或引用常量不能被返回 "F
nH>g-
qV^Z@N+,
Char *func(void) ?kfLOJQ:I
sem:"
{ y; LL^:rq
s+{)K
char str[]=”Hello Word”; sTx23RJ9
K&2{k+w
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 4\qnCf3
*c<=IcA
return str; .!yXto:
[=dK%7v
} WEgJ_dB
&jJj6
+P\
函数体内的指针变量并不会随着函数的消亡而自动释放 $j?zEz
~gz_4gzb
@VlDi1
八、一个内存拷贝函数的实现体 (~6oA f
!g=2U`j^
void *memcpy(void *pvTo,const void *pvFrom,size_t size) I<p- o/TP
Z(F`M;1>xI
{ 49vKb(bz{
.EJo9s'
assert((pvTo!=NULL)&&(pvFrom!=NULL)); DbRq,T
'6Lw<#It
byte *pbTo=(byte*)pvTo; //防止地址被改变 1D3{\v
g"pjWj)?
byte *pbFrom=(byte*)pvFrom; pY75S5h:
Gt>*y.]
while (size-- >0) y8jwfO3
>K<n~;ON|
pbTo++ = pbForm++; luNEgCq
UVND1XV^f
return pvTo; Yyl(<,Yi
_ISIq3A?
} `;?`XC"m
Tw^b!74gq
IGKF&s*;{[
九、内存的分配方式 8_yhV{
3iKBVN
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 v(5zSo
)YSS>V
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 ;[pY>VJ(
b#XY.+ *0
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 7OF6;@<
v?\Z4Z|f
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 NJ6*
7Cd
Ct-^-XD
g<ZB9;FX %
十、内存分配的注意事项 5,H,OZ}
JL[xrK0
用new或malloc分配内存时,必须要对此指针赋初值。 WS17DsWW
eiTG
用delete 或free释放内存后,必须要将指针指向NULL $^[^]Q
[FhFeW>
不能修改指向常量的指针数据 b/>L}/^PM
){~]-VK
%d3KE|&u
十一、内容复制与比较 )zUbMzF
<d&9`e1Hc
//数组…… E'_3U5U
hq.XO=0" k
char a[]=”Hello Word!”; {3s=U"\
(RhGBgp
char b[10]; =a!w)z_rw
gK8E|f-z
strcpy(b,a); S5a?KU
?g7O([*[
if (strcmp(a,b)==0) E@uxEF
iLd_{
{} 2<"kfan
J0%e6{C1
//指针…… #* KmPc+
Ze?(N~
char a[]=”Hello Word!”; 9^D5Sl$g
Wzm!:U2R*
char *p; ?+^vU5b1u
^)\z
p=new char[strlen(a)+1]; S.iCkX
*Fb|iR
strcpy(p,a); @nPXu2c?u7
eaNMcC1
if (strcmp(p,a)==0) R]Iv?)Y
$0(~ID
{} V~tZNRJ-
NG)Xk[q4
71)DLGL
十二、sizeof的问题 nqnVFkGd9
7[ 82~jM[
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 Q^p>hda
},tN{()
char a[]=”Hello World!” p`oSI}ZwB
r]6X
char *p=a; ;";#{B:
^nPk;%`0
count<<sizeof(a)<<end; //12字节
d q.'[
#KFpT__F
count<<sizeof(p)<<endl; //4字节 5:"zs
-D?-ctFYj^
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 u)NmjW
:h(r2?=7
void fun(char a[1000]) xRTr@
Y1=.46Ezf
{ j B.ZF7q
Oo-%;l`&
count<<sizeof(a)<<endl; //输出4而不是1000 KV1/!r+*
;XUiV$
} `fL81)!jI#
R=/^5DZ}
@_:Jm
tH<
十三、关于指针 |_ChK6Q?v
=~|:93]k
1、 指针创建时必须被初始化 Zo12F**{
2PaRbh{"
2、 指针在free 或delete后必须置为NULL *F_ dP
#z.QBG@
3、 指针的长度都为4字节
krt8yAkG
1kDr;.m%
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 {(00,6M)i
h3udS{9'8
char *p=new char[100]; Lt<KRs
XFS"~{
strcpy(p,”Hello World”); <E&[sQ|3
<0%X:q<
delete []p; //注意前面的[]号 (hb\1wZ
S|_} 0
p=NULL; ]CL9N
Q,AM<\S
5、数组指针的内容不能超过数组指针的最大容易。 QP%*`t?
a,EApUWw
如: L2NO_N
7?[{/`k~?
char *p=new char[5]; o5;V=8T;
[0lu&ak[&
strcpy(p,”Hello World”); //报错 目标容易不够大 [Y%H8}
@a[Y[FS
delete []p; //注意前面的[]号 .5ItH^
eG
F{.]
p=NULL; 0}:wM':G
u` j9m@`
8B|qNf `Yi
十四、关于malloc/free 和new /delete @An "ClDa
O=A(x m#
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 mqIcc'6f
Y,
?- []
l 注意:malloc/free是库函数,new/delete是运算符 0=,vdT
3%J7_e'
l malloc/free不能执行构造函数与析构函数,而new/delete可以 DXH"`1[-
aYC[15?'
l new/delete不能在C上运行,所以malloc/free不能被淘汰
wv6rjg:7
F~C9,`#Wf@
l 两者都必须要成对使用 <gtqwH]
VvS ^f
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 s/"l ?d
/ }tMb
?F!='6D}b
十五、C++的特性 }2 X"
n>5/y
c"/q
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 kv)IG$S0
<z2*T \B!8
重载和内联:即可用于全局函数,也可用于类的成员函数; H:x{qS4Si
ivi,/~L
Const和Virtual:只可用于类的成员函数; X
/
{;
r^jiK\*
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 A=+
|&+? t
,[j'OyR
覆盖是指派生类函数覆盖基类函数 ;`(l)X+7
'T_Vm%\)
函数名相同; K9@F1ccQ/
]-7$wVQ<
参数相同; <"SOH;w
|+|q`SwJ
基类函数必须有Virtual关键字; E#T6rd P
e; #"t
不同的范围(派生类和基类)。 )q>mt/,
fzhCV
隐藏是指派生类屏蔽了基类的同名函数相同 _rmTX.'w
YR\pt8(z?
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 $v#\bqY
WF!u2E+
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 Kj+=?R~}S
Sj`GP p
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 ;n"Nv}<C
$7~T+fmF
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 3EHn}#+U
c8"9Lv
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 7:cmBkXm
th 9I]g^=t
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: z;F6:aBa
8=!BtMd"
将void Func(A a) 改为void Func(const A &a)。 l JR
o2J-&
而void func(int a)就没必要改成void func(const int &a); a7_ &;
ZtFOIb*
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 SCUsDr+.
B,f4<
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 <NVSF6`
a#_=c>h;
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; 4)zHkN+
HLa3lUo
~%8T_R /3
十六、extern“C”有什么作用? SBNeN]
4J"S?HsW|
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 Km=dId7]
yGN2/>]
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 [
BpZ{Ql
jEkO#xI
d8o<Q 9
十七、构造函数与析构函数 qMj'% 5/
Ew9\Y R}
派生类的构造函数应在初始化表里调用基类的构造函数; <EHgPlQn
Pm
Zb!|
派生类和基类的析构函数应加Virtual关键字。 NukcBH
.0 [
zZ
不要小看构造函数和析构函数,其实编起来还是不容易。 x'c%w:
2A5R3x=\
#include <iostream.h> |IL/F]I
n*Q~<`T
class Base Q=+*OQV29
C(Bh<c0@
{ 7
B<
v *pN~}5
public: &ml7368@
+Ui @3Q
virtual ~Base() { cout<< "~Base" << endl ; } V2&O]bR
zK5/0zMZ
}; ZYi."^l
+;ILj<!Z7
class Derived : public Base C1V@\mRi
:L E&p[^
{ a(qij&>
k/hD2tBLu
public: de&*#O5
L7}dvdtZ0
virtual ~Derived() { cout<< "~Derived" << endl ; } f
<,E
'DDlX3W-
}; Tgf#I*(^]
dkr[B'n
void main(void) FM80F_G^z
)$.::[pNA
{ .d4L@{V
TH%J=1d
Base * pB = new Derived; // upcast 42Qfv%*c
- s}
delete pB; wd
4]Z0;
s\CZ os&
} /p&V72
Q^|ZoJS
输出结果为: mHiV};$
S1!X;PP/
~Derived H;eGBVi
g ss 3e&
~Base L355uaj
TVVr<r
如果析构函数不为虚,那么输出结果为 ^iHwv*ss
9}=]oX!+V
~Base ;F/yS2p
5 }pn5iI
cg]\R1Gm
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用
d&@>P&AT
lVw77bZ
仿止该头文件被重复引用