一、#include “filename.h”和#include <filename.h>的区别 !LSs9_w
uB+9dQ
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 R7K
/RF%1!M
K
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 5Bj77?Z
-N^=@Yx)
N{pa)
/
二、头文件的作用 ~= 9Vv
ZQLB`n@
加强安全检测 Vu|dV\N0*
c,BAa*]K
通过头文件可能方便地调用库功能,而不必关心其实现方式 g\J)= ,ju,
Ec.)!Hu
pGk"3.ce
三、* , &修饰符的位置 59MR|Jt
m+$/DD^-zl
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 }:^X X0:FK
Oy'0I,
a(Sv,@/
四、if语句 $~hdm$
7,su f }=
不要将布尔变量与任何值进行比较,那会很容易出错的。 1}DerX 6
z|%Bh
整形变量必须要有类型相同的值进行比较 p2a?9R
AO8:|?3S
浮点变量最好少比点,就算要比也要有值进行限制 [; F{mN
Zjt9vS)
指针变量要和NULL进行比较,不要和布尔型和整形比较 3:O+GQ*
[J:zE&aj
wy\o*P9mG)
五、const和#define的比较 e5qvyUJM
okh0_4
const有数据类型,#define没有数据类型 Fj3^
#ly
]TfeBX6ST
个别编译器中const可以进行调试,#define不可以进行调试 C&oxi$J:p+
:+1bg&wQ
在类中定义常量有两种方式 jDp]R_i
hgif]?:C<
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; SNxz*`@4
:7k`R62{
2、 用枚举代替const常量。 yHtGp%j
*|CLO|B)
/ (.'*biQ
六、C++函数中值的传递方式 m^Rd Iy)
=_pmy>_z
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference)
B,:23[v
a(g$ d2H
void fun(char c) //pass by value ?9,YVylg
o:f|zf>
i<
void fun(char *str) //pass by pointer +}\29@{W
2}>go^#O/w
void fun(char &str) //pass by reference IwnYJp:9v
y#nSk%"t"
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 iPNd!_
YBeZN98Nt
函数的类型不能省略,就算没有也要加个void (OQi%/Oy
QZ:v
%!D_q~"H
七、函数体中的指针或引用常量不能被返回 I}1fEw>8
)*+u\x_Hx
Char *func(void) Z!k5"\{0pE
@b8X%0B7
{ ul}4p{ m[
vr<)Ay
char str[]=”Hello Word”; A>[hC{
3l.Nz@a*
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 |zg=+
37,L**Dgs
return str; KgL<}=S
5=Zp%[#
} !;ZBL;qY9
6@i|Kw(:
函数体内的指针变量并不会随着函数的消亡而自动释放 /1H9z`qV
}isCvb
b ^+Fs
八、一个内存拷贝函数的实现体 ]kzv8#
;}n|,g>
void *memcpy(void *pvTo,const void *pvFrom,size_t size) t.gq5Y.[
[`cdlx?Eh
{ o8iig5bp
aViJ
assert((pvTo!=NULL)&&(pvFrom!=NULL)); _95- -\
C8!8u?k
byte *pbTo=(byte*)pvTo; //防止地址被改变 VM=hQYe
\=$EmHF
byte *pbFrom=(byte*)pvFrom; SxnIX/]J
{/th`#o4b
while (size-- >0) ~r{\WZ.
6sO
pbTo++ = pbForm++; U#OWUZ
j\%?<2dj=
return pvTo;
#_?426Wfs
XPGL3[w\V
} cH+h=E=
1kbT@
+R3\cRM
九、内存的分配方式 /h1dm,
yBJ/>SAcG
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 LuQ"E4;nY%
)er?*^9Z
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 Mb2:'u[
^aGZJiyJ
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 h[Ndtq>3{
Aqx3!
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 u^j8
XOT
OL,/-;z6
6M
O|s1zk
十、内存分配的注意事项 !N@S^JD6
wrZ7Sr!/V
用new或malloc分配内存时,必须要对此指针赋初值。 :w?:WH?2L
2GHXn:V
用delete 或free释放内存后,必须要将指针指向NULL /k4^&
JL}hOBqfI
不能修改指向常量的指针数据 Wq=ZU\Y
;:#?~%7>
HPu/. oE
十一、内容复制与比较 )*psDjZ7*
1 2%z3/i
//数组…… f}Ne8]U/Hc
c4!c_a2pS
char a[]=”Hello Word!”; Fi,e}j=2f
BK`Q)[
char b[10]; Wto@u4
B,BOzpb(
strcpy(b,a); 7eaA]y~H
sw 3:HNG=
if (strcmp(a,b)==0) GFASF,+
:,xyVb+
{} gQ[]
c%xED%X9
//指针…… }mtC6G41Q
z&;zU)Jvd
char a[]=”Hello Word!”; Mhu53DT
ft~|
char *p; tu?Z@W/
(R;)
9I\
p=new char[strlen(a)+1]; i5L+8kx4
PMz{8
F
strcpy(p,a); ?9wFV/
FOlA* U4U
if (strcmp(p,a)==0) N+C%Z[gt[
MHpL$g=5_
{} P ],)
!9e\O5PmO
P!)7\.7
十二、sizeof的问题 {|7OmslC@
\
pe[V~F
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 o1p$9PL\:
:$GL.n-?
char a[]=”Hello World!” p ?Ij-uo"o
QXIbFv
char *p=a; +[ZMrTW!0C
$,z[XM&9)
count<<sizeof(a)<<end; //12字节 [i<$ZP
FJn~
=hA
count<<sizeof(p)<<endl; //4字节 v
,G-k2$Qe
Yq)YS]
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 #LrCx"_&
u$Pf.#
void fun(char a[1000]) m"?'hR2
/`j K
{ j"D0nG,
\ eyQo>(
count<<sizeof(a)<<endl; //输出4而不是1000 C,VqT6E<
f/IRO33
} w ufKb.4`
yv8dfl
Qn'r+X5t
十三、关于指针 5w,YBUp
5wE !_ng>|
1、 指针创建时必须被初始化 r=P$iG'&
_>_ y@-b
2、 指针在free 或delete后必须置为NULL 0%&fUz36E6
2os6c te
3、 指针的长度都为4字节 56O<CgJF<
yaYIgG
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 {%+3D,$)
]'
"^M
char *p=new char[100]; 3' :[i2[
!w;A=
strcpy(p,”Hello World”); 00.iMmJ
v%l|S{>(
delete []p; //注意前面的[]号 O+8ApicjTc
}HA2ce\
p=NULL; ]Xkc0E1
\3y=0
5、数组指针的内容不能超过数组指针的最大容易。 |V~(mS747:
O7<V@GL+
如: 5f^`4pT
x1hs19s
char *p=new char[5]; b$`4Nn|
GD6'R"tJ
strcpy(p,”Hello World”); //报错 目标容易不够大 /kviO@jm4(
wJ]$'c3
delete []p; //注意前面的[]号 2AdHj&XE
A0N ;VYv
p=NULL; xUYN\Pc-
JY050FL
m?R+Z6c[
十四、关于malloc/free 和new /delete ~]_jKe4W
pg}DC0a
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 r^o}Y
dv4r\ R^
l 注意:malloc/free是库函数,new/delete是运算符 \<MTY:
][$$
=
l malloc/free不能执行构造函数与析构函数,而new/delete可以 aY1#K6(y
eQ)ioY
l new/delete不能在C上运行,所以malloc/free不能被淘汰 ['N#aDh.?
?;.+A4
l 两者都必须要成对使用 WG[0$j
k f K"i
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 fY+ .#V
/*R' xBr
@1qUC"Mg
十五、C++的特性 A&_i]o
?k7/`gU
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 dU04/]modD
}"; hz*a
重载和内联:即可用于全局函数,也可用于类的成员函数; 5A=xF j{
@ :
Const和Virtual:只可用于类的成员函数; #<V'gE
~zOU/8n
,F
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 ewff(e9
$}h_EI6hS
覆盖是指派生类函数覆盖基类函数 \?mU$,voI
}y=n#%|i.
函数名相同; #(Yb
lY
W!9f'Yn
参数相同; B xN#Nk~
+WEO]q?K
基类函数必须有Virtual关键字; +VI0 oo {Z
`9"jHw`D
不同的范围(派生类和基类)。 'w$we6f
"e};?|y
隐藏是指派生类屏蔽了基类的同名函数相同 '`A67bdq)
8w@jUGsc
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 E=U^T/
%$-3fj7
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 [`nyq )
?B31t9
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 9lwo/(s
$/(/v?3][e
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 +wgUs*(W
ewlc ^`
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 { dxyBDK
)UU6\2^
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: %;XuA*e
NZ? =pfK\s
将void Func(A a) 改为void Func(const A &a)。 Wv'B[;[)
Fl(ZKpSZU
而void func(int a)就没必要改成void func(const int &a); ea;c\84_N
a{YVz\?d}
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 -8J@r2 \
3G0\i!*t
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 \Hx#p`B%
rlh6\Fa
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; ~CTRPH
5UD;ZV%
=|zyi|
十六、extern“C”有什么作用? ;iI2K/ 3
/]58:euR
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 j{+I~|ZB,
7.'j~hJL
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 ]V7hl#VO
dufHd
KD<`-b)7<
十七、构造函数与析构函数 @?NLME
`)_FO]m}jS
派生类的构造函数应在初始化表里调用基类的构造函数; |"&4"nwa
TgG)btQ
派生类和基类的析构函数应加Virtual关键字。 ;Cpm3at
yq^$H^_O
p
不要小看构造函数和析构函数,其实编起来还是不容易。 R1%T>2"~&
lk'jBl%
#include <iostream.h> fO|u(e
?O]gFn
class Base 5 `mVe0uI
"@bk$o=
{ 'n`$c{N<tM
,=yIfbFQ
public: _'v )Fy
({62GWnn_
virtual ~Base() { cout<< "~Base" << endl ; } iFT3fP'> 5
Xq$0% WjG
}; nr6[rq
::t!W7W
class Derived : public Base K_Gf\x
1Ee>pbd
{ 1KEPD@0oxx
C'"6@-~
public: g)Uh
~0t'+.
virtual ~Derived() { cout<< "~Derived" << endl ; } ITOGD
D'=`O6pK
}; gKEvgXOj
G4]``
void main(void) _dY}86{
v<4X;4p^
{ *Fs^T^ ?r
s7gf7E#Y
Base * pB = new Derived; // upcast F.w#AV
$:P~21,
delete pB; <0MUn#7'
7E]l=Z`x
} A~t7I{`
r F-yD1
输出结果为: .5zJ bZ9
CF4y$aC#
~Derived Sa(rl^qZ2
"@Fxfd+Ot
~Base 'S
;vv]}Gs
~nlY8B(
如果析构函数不为虚,那么输出结果为 Np)!23 "
W12K93tO
~Base Gj0NN:
vpMv
ot6Pq}
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 3Pq)RD|hn
sRG3`>1
仿止该头文件被重复引用