一、#include “filename.h”和#include <filename.h>的区别 !O)je>A
QC\r|RXW
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 #su R[K*S
Z$*m=]2
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 ,8.Fd|#L
.)(5F45Wg
(1%O;D.*?{
二、头文件的作用 N>V\
uuaoBf
加强安全检测 ?uAq goCl
A4K8DP
通过头文件可能方便地调用库功能,而不必关心其实现方式 K92nh/}y
6(pa2
gh9Gc1tKt
三、* , &修饰符的位置 Pzt5'O@dA
cG)U01/"
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 C>NLZMT
F)8M9%g5m
s2=`haYu
四、if语句 {!0f.nv
wXR7Ifrv
不要将布尔变量与任何值进行比较,那会很容易出错的。 f]sc[_n]
\wR;N/tg
整形变量必须要有类型相同的值进行比较 '@6O3z_{
R6m6bsZ`
浮点变量最好少比点,就算要比也要有值进行限制 "!S7D>2y#
%+pF4f8]
指针变量要和NULL进行比较,不要和布尔型和整形比较 )L+>^cJI<
J;DTh ]z?:
bVxbQ$
五、const和#define的比较 to9X2^
aM5Hp>'nI
const有数据类型,#define没有数据类型 tD^$}u6
,DL%oQR
个别编译器中const可以进行调试,#define不可以进行调试 l=&\luNz
ZrNBkfe:
在类中定义常量有两种方式 )U|0vr8:
~o8
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; `g}po%k
dDrzO*a\
2、 用枚举代替const常量。 q<XleC
f7_V ]
9P1!<6mN\
六、C++函数中值的传递方式 :pJKZ2B,
T)#e=WcP]
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) a&z$4!wQB
.;J6)h
void fun(char c) //pass by value aN5"[&
oUd R,;h9
void fun(char *str) //pass by pointer /1BqC3]tL
jR[b7s
void fun(char &str) //pass by reference JZup} {a
7lUnqX.
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 w~AW(
VX
mufXM(
函数的类型不能省略,就算没有也要加个void u>\u}c
'z9}I
#
dKpUw9C#/
七、函数体中的指针或引用常量不能被返回 [QDM_n
a{
p1Yy-]
Char *func(void) X..<U}e
.Lm0$o*`
{ ){< qp
9dCf@5]
char str[]=”Hello Word”; eWGaGRem
ET0^_yk
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 \o}=ob
=/m$ayG
return str; fB=j51Lw
4^GIQEjx
} "1wjh=@z
.b|!FWHNS
函数体内的指针变量并不会随着函数的消亡而自动释放 q[TGEgG
D KRF#*[=d
i%GNmD
八、一个内存拷贝函数的实现体 yPoa04!{=
TCI)L}L|
void *memcpy(void *pvTo,const void *pvFrom,size_t size) 4N(iow4
*v#Z/RrrA
{ T+j-MR}{\
&BxZ}JH=k
assert((pvTo!=NULL)&&(pvFrom!=NULL)); je;|zfe]
g3| 62uDF
byte *pbTo=(byte*)pvTo; //防止地址被改变 LV8{c!"
X:JU#sI
byte *pbFrom=(byte*)pvFrom; rVM?[_'O
!j%#7
while (size-- >0) 'FM_5`&
8
3Tv-X
pbTo++ = pbForm++; r7+Ytr
G%MdZg&i
return pvTo; MlV3qM@
B=)tq.Q7
} ih=O#f|
)mu[ye"p
BIxjY!!"
九、内存的分配方式 H;N6X y*~
y:YJv x6&4
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 |"+UCAU
CwaW>(`v
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 u=
Vt3%q
G2yQHTbl
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 H~;s$!lG
}qg.Go
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 m](q,65 2
#k
t+
)>
=JE5/
十、内存分配的注意事项 /s
Bs eI
Zvkb=
用new或malloc分配内存时,必须要对此指针赋初值。 \:jJ{bl^A
`zOn(6B;U
用delete 或free释放内存后,必须要将指针指向NULL :Izdj*HL;A
,In}be$:
不能修改指向常量的指针数据 [j 'lB
WesEZ\V
AGV+Y6
十一、内容复制与比较 BnU3oP
Qe;R3D=T;
//数组…… .R_-$/ZP
,.i)(Or
char a[]=”Hello Word!”; #{g6'9PMz
] p*Fq^
char b[10]; 8Z>=sUMQ
MI,kKi
strcpy(b,a); F.iJz4ya_
@DuSii#.S
if (strcmp(a,b)==0) 4Un%p7Y~
;3&HZq6Z (
{} 15_Px9
+:&|]$8<
//指针…… FvVM}l'
Rg7~?b-
char a[]=”Hello Word!”; [orS-H7^
fzr0dcNgM
char *p; >k8FUf(c
lNx:_g:SrZ
p=new char[strlen(a)+1]; *n_7~ZX
|W*i'E
strcpy(p,a); Vi>`g{\
evlz R/
if (strcmp(p,a)==0) uF\ ;m.
XXy&1C
{} ]5+<Rqdbg
R]"
jr
h@+(VQ
十二、sizeof的问题 -Q"
N;&'[&
MNocXK
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 =2/[n8pSsM
.9!?vz]1
char a[]=”Hello World!” S?u@3PyJm
y\mK?eR
char *p=a; z+]YB5zK%
LfX[(FP
count<<sizeof(a)<<end; //12字节 l{t!
LTf;
PvW~EJ
count<<sizeof(p)<<endl; //4字节 cm`x;[e6l
=j~Xrytn
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 &6^QFqqW`-
<nJ8%aY,
void fun(char a[1000]) ]]50c
'7UIzk|
{ "p"~fN
/I9
lx&;?QQ
count<<sizeof(a)<<endl; //输出4而不是1000 u.,l_D_
I5#zo,9
} NU%<Ws=
O[^u<*fi{
:\KJw
十三、关于指针 $kxP{0u
N _|tw
1、 指针创建时必须被初始化 hw0u?++
Pvz\zRq
2、 指针在free 或delete后必须置为NULL O_^;wey0}?
?U(`x6\:
3、 指针的长度都为4字节 ?btZdnQ))S
#_'|
TT>p#
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 '<Jqp7$dL
1(jDBP!8
char *p=new char[100]; *V?p&/>MT
%<@x(q
strcpy(p,”Hello World”); (}MN16!
T*rx5*:o
delete []p; //注意前面的[]号 2-_d~~O1N
4+q3
Kw
p=NULL; ,7ZV;f81
6HRr4NDcj
5、数组指针的内容不能超过数组指针的最大容易。 ,L$,d
Y(6 p&I
如: 9K4Jg]?
DGO\&^GT^
char *p=new char[5]; x?RYt4 S
O9R[F
strcpy(p,”Hello World”); //报错 目标容易不够大 zA*I=3E(
3oMhsQz~z
delete []p; //注意前面的[]号 dr]Pns9
S(Q=2Y
p=NULL; Qb?eA
st wxF?\NS
[6f(3|"
十四、关于malloc/free 和new /delete {R}Kt;L:Ut
j S<."a/n
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 WbGN
5?9Q
@q+X:K5b
l 注意:malloc/free是库函数,new/delete是运算符 1[ 40\ sM
h4tAaPcS+
l malloc/free不能执行构造函数与析构函数,而new/delete可以 LuvRxmQ`
@aUQy;
l new/delete不能在C上运行,所以malloc/free不能被淘汰 E{xcu9
/eY}0q%
l 两者都必须要成对使用 UpS7>c7s
><H*T{
Pg
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 U flS`
1XJLGMW,
Wph@LRB]
十五、C++的特性 67A g.f6-
Z&Xp9"j,@;
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 WFG`-8_e[I
h+j{;evN
重载和内联:即可用于全局函数,也可用于类的成员函数; `!@d$*:'
r0,XR
Const和Virtual:只可用于类的成员函数; i2X%xYv ^
BTDUT%Yfg
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 vY!'@W
FS7@6I2Ts
覆盖是指派生类函数覆盖基类函数 oP_}C[
1)hO!%
函数名相同; tPaNhm[-q7
Zk>#T:{h
参数相同; B;c2gu
C^*3nd3
基类函数必须有Virtual关键字; k%%0"+y#a
yhh\?qqy
不同的范围(派生类和基类)。 z~Is
E8
@ ('/NjTZ
隐藏是指派生类屏蔽了基类的同名函数相同 CJe~>4BT
4^_'LiX3[
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 9qI#vHA
P~M<OUg
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 "g:1br?X,9
!U4<4<+
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 jP}Ix8vc=
DE!c+s_g4
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 }fh<L CwTi
q6EZ?bo{
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 <3!Q Xc
tO+Lf2Ni+
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: ].HHTCD`c
m aOt/-
将void Func(A a) 改为void Func(const A &a)。 T_Cj=>L
+{L=cWA"
而void func(int a)就没必要改成void func(const int &a); S,vh
a~&euT2
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 ,$(a,`s)
2 `U+
!
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 D+"+m%^>C
v4vIcHDs
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; X ;Cl8
uYCWsw/
:N64FR#
十六、extern“C”有什么作用? f f5 e]^,
CkR
95*
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 Y(B3M=j
Sy"!Q%+|
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 c0QKx=
`Jn2(+
y&6 pc
十七、构造函数与析构函数 JS^!XB'!
PnZY%+[I
派生类的构造函数应在初始化表里调用基类的构造函数; #AF.1;(k
`oOVR6{K9
派生类和基类的析构函数应加Virtual关键字。 ^NXxMC(e+
]h%~'8g,
不要小看构造函数和析构函数,其实编起来还是不容易。 *AJYSa,z
B3&C=*y
#include <iostream.h> {ep.So6
)4^Sz &\
class Base S`pB EM
`y$@zT?j
{ szGGw
eXi}-~o
public: 4(&sw<k
" 2Q*-
virtual ~Base() { cout<< "~Base" << endl ; } p|Qn?^C:
?H!QV;ku
}; Igh=Z %
Y3O/`-9i
class Derived : public Base rw.DKM'
_*++xF1
{ th%T(D5n
Wo{4*~f
public: #Wq@j1?
#vzt6x@*
virtual ~Derived() { cout<< "~Derived" << endl ; } 6e%ZNw{#=
eI1C0Uz1
}; ?g4S51zpp
GDYFhH7H
void main(void) 5xhYOwQBo
7V-uQ)*
{ i2E@5 v=|Y
PO*0jO;%
Base * pB = new Derived; // upcast " TC:O^X
oAgU rl;R
delete pB; I ;F\'P)e
.* &F
} &M7AM"9
v9"03=h
输出结果为: +LF`ZXe8l
(BGflb
~Derived SW7AG;c=
3;F up4!4}
~Base ` >[Offhd
cUr5x8<W).
如果析构函数不为虚,那么输出结果为 _ ( $U\FW
7{p6&xXx
~Base NIG*
}[}P
L[tq@[(IJ
2%vG7o,#
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 APyH.] mQ
EN5F*s@r
仿止该头文件被重复引用