一、#include “filename.h”和#include <filename.h>的区别 d2#NRqgQ
1l#46?]~
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件
F/5G~17
?QT6q]|d0+
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 %T]^,y$n
;(/go\m
tB
?<!qF:r:
二、头文件的作用 b+|Jw\k
l5Bm.H_
加强安全检测 FHr)xqo=~
W34xrm
通过头文件可能方便地调用库功能,而不必关心其实现方式 Ldz]FB|
Z\CvaX
|z=`Ur@)
三、* , &修饰符的位置 Mc@9ivwL#
uH9Vj<E$K
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 B&a{,.m&q6
gE2(E0H
<x^$Fu
四、if语句 H<_Tn$<zH.
V@`b7GM
不要将布尔变量与任何值进行比较,那会很容易出错的。 7<^+)DsS?
s0?'mC+p
整形变量必须要有类型相同的值进行比较 kzRvLs4xM
hc|A:v)]
浮点变量最好少比点,就算要比也要有值进行限制 t`K9K"|k
pRobx
指针变量要和NULL进行比较,不要和布尔型和整形比较 kBR=a%kG
AhF@
?l9sj]^w
五、const和#define的比较 ,IPt4EH$
TRi#
const有数据类型,#define没有数据类型 #AGO~#aK
!
*sXLlS
个别编译器中const可以进行调试,#define不可以进行调试 b\(f>g[
~DK.Y
在类中定义常量有两种方式 f 3H uT=n
r*`e%`HU
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; 7p.8{zQ*
0vqH-)}
2、 用枚举代替const常量。 4@0aN6Os
n>v1<^
%HG+|)b
六、C++函数中值的传递方式 cj2Smgw&>
Z3TCi7,m
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) w PR Ns9^
K:U=Y$ x
void fun(char c) //pass by value "^$Ht`p[
1-p#}VX
void fun(char *str) //pass by pointer eQ[akVMk
~RbVcB#
void fun(char &str) //pass by reference 1/9*c *w
F7=9> ,
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 vb~%u;zrC@
bDvGFSAH
函数的类型不能省略,就算没有也要加个void `?$-T5Rr
.\a+m
h/\v+xiF
七、函数体中的指针或引用常量不能被返回 %h ;oi/pe
\2/X$x<?X
Char *func(void) KcV"<9rE
lD$s, hp
{ Lmjd,t
C,W@C
char str[]=”Hello Word”; Jzf+"%lv
jj&G[-"bv
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 I '0[
3/vtx9D
return str; _(f@b1O~
l)$mpMgAD
} qOG@MR(5
TE&E f$h
函数体内的指针变量并不会随着函数的消亡而自动释放 |5;,]lbt
i%133in
<T7@,_T
八、一个内存拷贝函数的实现体 *=@8t^fa86
)q'dX+4=eL
void *memcpy(void *pvTo,const void *pvFrom,size_t size) \Nik`v*Pd
%.
((4 6)
{ X#axCDM-
G--vwvL
assert((pvTo!=NULL)&&(pvFrom!=NULL)); <tTNtBb
E*)A!2rlK
byte *pbTo=(byte*)pvTo; //防止地址被改变 ;
]%fFcy
z]g#2xD2
byte *pbFrom=(byte*)pvFrom; d
>L8SL
^e "4@O"
while (size-- >0) =z5=?
AIl`>ac
pbTo++ = pbForm++; 1<x5{/CZ
WClprSl8
return pvTo; hlyh8=Z6o
X ([^i;mr
} j*8Ze!^
ShRMzU
FBP #_"z
九、内存的分配方式 KX x+J}n
J8FzQ2
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 gz'{l[
\W_ Dz*N
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 G8F;fG N
Fc=F2M o?
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 aEQrBs
)e[q%%ks
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 .nr%c*JUp
U#Kw+slM
LVP6vs
十、内存分配的注意事项 2hntQ1[
!b K;/)
用new或malloc分配内存时,必须要对此指针赋初值。 5-a^Frmg#"
jz'%(6#'gW
用delete 或free释放内存后,必须要将指针指向NULL /q]fG
\8Ewl|"N:u
不能修改指向常量的指针数据 T}p|_)&y
j}h%,
7
KPK`C0mg@k
十一、内容复制与比较 V!e`P
-K^(L#G
//数组…… *JW.ca}
f:t5`c.
char a[]=”Hello Word!”; M+=q"#&
/KiaLS
char b[10]; m&*0<N
}/ xdHt
strcpy(b,a); PwAmnk !
_}`y3"CD7
if (strcmp(a,b)==0) GO#eI]>/r
&6Wim<*
{} $iy(+}
Y^?PHz'Go
//指针…… ]w8h#p
Zg])uM]\2i
char a[]=”Hello Word!”; :d~&Dt<c
G)5Uiu:^X
char *p; [/cJc%{N
j~ qm5}
p=new char[strlen(a)+1]; RoD9
j]9,yi
strcpy(p,a); /3`fO^39Ta
{2&MyxV
if (strcmp(p,a)==0) sMw"C~XL
=?B[oq
{} aOW~! f/M
w4&-9[@Y
Yceex}X*5
十二、sizeof的问题 -uK@2}NZ
TkjZI}]2
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 HtI>rj/\
x
B{_-k
char a[]=”Hello World!” Q mz3GH@wg
(7PVfS>;
char *p=a; 3DrW[\
62xAS#\K>
count<<sizeof(a)<<end; //12字节 =$%_asQJ
}Mh`j$
count<<sizeof(p)<<endl; //4字节 M#]URS2h<O
U| 1&=8l
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 .$-%rU:*}
8F`799[p
void fun(char a[1000]) U[l{cRT
&
Mf nH
{ |Q~5TL>b
m[*y9A1
count<<sizeof(a)<<endl; //输出4而不是1000 ![@\p5-e
`lq[6[n
} A&;Pt/#'
bMF`KRP2
N%+ C5e<
十三、关于指针 TYr"yZ([
'4d+!%2t
1、 指针创建时必须被初始化 ig,v6lqhM
5-X(K 'Q
2、 指针在free 或delete后必须置为NULL #_OrS/H
2JRX ;s~
3、 指针的长度都为4字节 wrt^0n'r)c
GGwHz]1L
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 k7Z1Y!n7
f)K1j{TZ
char *p=new char[100]; |yow(2(F@
dy*CDRU4
strcpy(p,”Hello World”); k%?A=h
$3MYr5
delete []p; //注意前面的[]号 qy|si4IU8,
-( ,iwFb
p=NULL; t{)J#8:g
x?B 8b-*
5、数组指针的内容不能超过数组指针的最大容易。 ^iq$zHbc0u
{n>W8sN<
如: GiN\@F!
Mw+8p}E
char *p=new char[5]; }PDNW
wmr8[n&c
strcpy(p,”Hello World”); //报错 目标容易不够大 h
.$3jNU
PH}^RR{H[
delete []p; //注意前面的[]号 BSu
]NOwe
77ID
82
p=NULL; %v(\;&@
_:tisr{
aGz<Yip
十四、关于malloc/free 和new /delete \WeGO.i-
)cy_d!
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 ES#K'Lf
j.@TPf*
l 注意:malloc/free是库函数,new/delete是运算符 !mX 2
A"@C }f
l malloc/free不能执行构造函数与析构函数,而new/delete可以 {s=$.Kg
"K8<X
l new/delete不能在C上运行,所以malloc/free不能被淘汰 YbrsXp"
`_;VD?")*l
l 两者都必须要成对使用 v5 yOh5
b)A$lP%`
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理
C9q`x2
c!BiGw,;
7='M&Za
十五、C++的特性 ? 1g<] ?
TY=BP!s
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 ~pqp`
'lU9*e9
重载和内联:即可用于全局函数,也可用于类的成员函数; ;!k1LfN
(,E.1j]ji
Const和Virtual:只可用于类的成员函数; vTD`Ja#h
S)[`Bm
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 PF1m :Iz`d
H5Rn.n( |
覆盖是指派生类函数覆盖基类函数 JeJc(e
nJYcC"f
函数名相同; ]OoqU-q
.!
LOhZ
参数相同; DiAPs_@
LmLV2f
基类函数必须有Virtual关键字; $H/3t? 6h`
/0 ,#c2aq
不同的范围(派生类和基类)。 ?Ee HeN_
EM*YN=S o
隐藏是指派生类屏蔽了基类的同名函数相同 H;<hmbN?d
}0T1* .Cz
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 r}P{opn$t
~_SV`io
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 x~}RL-Y2o
}`yIO"{8n
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 6tM CpSJ
77OH.E|$
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 16 o3ER
j]6j!.1
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 s} ,p>8
fAf sKO*
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如:
b:>(U.
q]tPsX5{*
将void Func(A a) 改为void Func(const A &a)。 v\t$. _at
lC.Yu$O5
而void func(int a)就没必要改成void func(const int &a); A%u-6"
S
1|[}nYP
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 <?,o
{
QdG_zK>|e
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 9S.Uo[YY
RNiZ2:
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; b IcLMG
s
O GrVy=rd
[,-MC7>]
十六、extern“C”有什么作用? #P-S.b
W z3y+I/&
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 VVvV]rU~
F`U%xn,
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 ,'F;s:WM,
f>5{SoM
vKDRjrF-
十七、构造函数与析构函数 cI'&gT5
<r,l
派生类的构造函数应在初始化表里调用基类的构造函数; ;&P%A<[`
v?)JM+
派生类和基类的析构函数应加Virtual关键字。 ge[f/"u
s*:J=+D]G
不要小看构造函数和析构函数,其实编起来还是不容易。 $)mE"4FE
t&wtw
#include <iostream.h> kh 17
>"B95$x5
class Base xRJv_=dT
1/3Go97/qV
{ b-@VR
+o!".Hp
public: ^:\|6`{n
G#8HY VF
virtual ~Base() { cout<< "~Base" << endl ; }
qn6Y(@<[
f$NudG!S
}; D(s[=$zua
&
p"ks8"
class Derived : public Base 'AE)&56
%:N6#;l M
{ vN-#Ej.
u
{$ HW_\w
public: 1[a;2xA~
*;(LKRV
virtual ~Derived() { cout<< "~Derived" << endl ; } +L!-JrYHS4
C6ZM#}I$l
}; j>+x|!k
Ni'vz7j
void main(void) #q%xJ[
c</d1x T
{ OnC|9
]ZelB,7q
Base * pB = new Derived; // upcast _0 USe
(01M 0b#
delete pB; ~C{d2i
~#&bDot
} +g<2t,
cnXIE{9M
输出结果为: Fa,a)JY>
vAbMU
~Derived 9;k_"@A6
l!<Nw8+U
~Base E#`=xg
{^1GHU
如果析构函数不为虚,那么输出结果为 \Q|1I
Bl2y~fCA
~Base
5 .
5
@>_`g=
h )"PPI
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 @H"~/ m_o
b !J21cg<L
仿止该头文件被重复引用