一、#include “filename.h”和#include <filename.h>的区别 WJShN~ E
OxlA)$.hpu
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 :cT)M(o
7FB?t<x
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 jk AjYR .
M&Uy42,MR
h3ygL" k
二、头文件的作用 o-,."|6
7+O)AU{
加强安全检测 )DSeXS[
e
@KN+)q P
通过头文件可能方便地调用库功能,而不必关心其实现方式 DiC z%'N
%()d$.F
i! .]U@{k
三、* , &修饰符的位置 cG|fau<G
ZlT }cA/n
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 ,/;Aew;
Dd3f@b[WX
=~D? K9o
四、if语句 E
C?}iP
ewDYu=`*
不要将布尔变量与任何值进行比较,那会很容易出错的。 Wn%P.`o#
O[@!1SKT0
整形变量必须要有类型相同的值进行比较 X+hHE kJ
8fC4j`!
浮点变量最好少比点,就算要比也要有值进行限制 a)_3r]sv^
'o AmA=
指针变量要和NULL进行比较,不要和布尔型和整形比较 W5*ldXXk
K$"#SZEi
&i#$ia r
五、const和#define的比较 |;ztK[(
TCr4-"`r-{
const有数据类型,#define没有数据类型 87 Z[0>
'-iEbE
个别编译器中const可以进行调试,#define不可以进行调试 du65=w4E!
%I1@{>OxG
在类中定义常量有两种方式 6g(;2gY
s :vNr@TS
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; :@A&HkF
~q$]iwwqT
2、 用枚举代替const常量。 HJL! ;i
Q$%apL
/6x&%G:m#
六、C++函数中值的传递方式 ]\,?u /
AdX))xgl
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) ?&B8:<qy;L
J_Lmy7~xbD
void fun(char c) //pass by value Gh;\"Qx
TI>5g(:3\
void fun(char *str) //pass by pointer Q(|@&83].
GQ2GcX(E(
void fun(char &str) //pass by reference $?= $F
*?)MJ@
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 RS5<] dy
>m%_`68
函数的类型不能省略,就算没有也要加个void ah>c)1DA*H
!)s(Lv%]
aLk3Yg@X
七、函数体中的指针或引用常量不能被返回 m+QS -woHn
]'.qRTz'\t
Char *func(void) ot0teNF
>xWS>
{ 1p&.\ ^
uGU2
char str[]=”Hello Word”; sh/,"b2!P
@0 +\:F
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 =RoE=)1&-
5 jrR]X
return str; ]U?nYppV
corm'AJ/
} dOjly,!
pdu1 kL
函数体内的指针变量并不会随着函数的消亡而自动释放 $LP(\T([
2&6D`{"P
x]^d'o:cDP
八、一个内存拷贝函数的实现体 FFT)m^4p.
V@'Xj .ze
void *memcpy(void *pvTo,const void *pvFrom,size_t size) >a;a8EA<O
7nt(Rtbsu
{ #MC#K{Xd
1+%UZK= K
assert((pvTo!=NULL)&&(pvFrom!=NULL)); %bcf% 7
?QP>rm
byte *pbTo=(byte*)pvTo; //防止地址被改变 " ityx?
Y3~Uz#`SU
byte *pbFrom=(byte*)pvFrom; GT6; I7
g=:o 'W$@
while (size-- >0) SSe;&Jk2d
^ AZ#tp%)
pbTo++ = pbForm++; $z=a+t *
|d0X1(
return pvTo; D+T/ Z)
{_7hX`p
} 0\mf1{$"!7
2/SUEnaLy_
S|tD8A
九、内存的分配方式 '4,?YcZ?S
z,Xj$wl
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 Zpd-ob
v.ZUYa|
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 5BrN
uR$
"6,fIsU
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 l;M,=ctB(
^EIuGz1@0
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 !(*&P
?e%*q^~Cu
2Z; !N37U
十、内存分配的注意事项 enk`I$Xx
=svFw&q"
用new或malloc分配内存时,必须要对此指针赋初值。 Wvb ~j
g?
vz\_
用delete 或free释放内存后,必须要将指针指向NULL %YVPm*J~
:k9T`Aa]
不能修改指向常量的指针数据 l!1_~!{y
`.@udfog^0
4KH'S'eR
十一、内容复制与比较 R3g)LnN
Q g/Rw4[
//数组…… Xl=RaV^X"
65Z}Hf
char a[]=”Hello Word!”; 8P]nO+
&D<6Go/)_*
char b[10]; nw+t!C
<gPM/4$G
strcpy(b,a); UV(`.
nscnG5'{+
if (strcmp(a,b)==0) ll__A|JQ
[C!*7h
{} 4EYD5
z/#,L!Z3
//指针…… A}"|_&E
nLL2/!'n
char a[]=”Hello Word!”; D)MFii1J~
I(UK9H{0$
char *p; 7<LuL
drpx"d[c
p=new char[strlen(a)+1]; 0L;,\&*u
Vc0j)3
strcpy(p,a); G/
si( LK
2fdN@iruB
if (strcmp(p,a)==0) 23|JgKuA
f0eQq;D$K
{} Mn5(Kw?o2J
I484cR2.
e@c8Ce|0
十二、sizeof的问题 !- [ZQ
zMepF]V
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 "IS; o o$g
E2l"e?AN~
char a[]=”Hello World!” ~LI }
<Z[Z&^
char *p=a; #0)TS
N?3p,2
count<<sizeof(a)<<end; //12字节 -Tvnd,
P|1 D6
count<<sizeof(p)<<endl; //4字节
/1TK+E$
EFiVwH
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 ys!O"=OJ
]G&[P8hzB
void fun(char a[1000]) .|"E:qTD
5xT, O
{ E 9Kp=3H
krGIE}5
count<<sizeof(a)<<endl; //输出4而不是1000 Sj)?!
ZYB5s~;eB"
} ,1~B7Zd
aQH]hLvs
51%Rk,/o
十三、关于指针 |5(CzXR]
2K3j3 |T
1、 指针创建时必须被初始化 Sc3{Y+g
3Ch42<
2、 指针在free 或delete后必须置为NULL J<NpA(@^
Cm5L99Y
3、 指针的长度都为4字节 Ww~C[8q
W rT_7
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 Nnn~7
5~>j98K
char *p=new char[100]; GQ85ykky
@WXRZEz
strcpy(p,”Hello World”); HI1|~hOb'
io"NqR#"v
delete []p; //注意前面的[]号 5T"h7^}e
m[l&&(+J,
p=NULL; +-x+c:
IxA
3 p -SpUvp
5、数组指针的内容不能超过数组指针的最大容易。 ^-Ks_4
/=V!lRs
如: xn=mS!"1Zo
}<z[t5
char *p=new char[5]; LvGo$f/9
W-D4"
G@
strcpy(p,”Hello World”); //报错 目标容易不够大 sw$JY}Q8x
(w_b
delete []p; //注意前面的[]号 *?Oh%.HgF
g}?39?o4
p=NULL; XYV`[,^h&
Oo!]{[}7
.|:(VG$MfI
十四、关于malloc/free 和new /delete ,LOx!
'[[IalQ?
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 0/fwAp
.K_50%s
l 注意:malloc/free是库函数,new/delete是运算符 "SKv'*\b
wd,6/5=lh
l malloc/free不能执行构造函数与析构函数,而new/delete可以 1JS5 LS
%}
l new/delete不能在C上运行,所以malloc/free不能被淘汰 t }K8{
V
AHa]=ka>
l 两者都必须要成对使用 AgDXpaq
EAs^i+/
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 .dc|?$XV
IQ JFL
+f
'\pSUp
十五、C++的特性
8`<3rj
us#ji i.<
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 3D,tnn+J
rv~OfL
重载和内联:即可用于全局函数,也可用于类的成员函数; W
Emh
eH;{Ln
Const和Virtual:只可用于类的成员函数; | m#"
meD83,L~N
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 h?QGJ^#8
2 I.Q-'@
覆盖是指派生类函数覆盖基类函数 !4"$O@U4
?;rRR48T9E
函数名相同; P?=}}DI
o3'Za'N.
参数相同; &61h*s
PTF|"^k+
基类函数必须有Virtual关键字; |i(@1 l
L>`inrpz=w
不同的范围(派生类和基类)。 :9|CpC`.
o^d
隐藏是指派生类屏蔽了基类的同名函数相同 BS?rKtdm(
Q-e(>=Gv_
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 9 KU3)%U
J32"Ytdo<
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 aqP"Y9l
m4 c2WY6k
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 A2nL=9~
/p{$HkVw
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 qwuA[QkPi
S8e ?-rC
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 }vX1@n7T6
9+'*
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: e1H2w?
s
\uOR1z
将void Func(A a) 改为void Func(const A &a)。 %G,d&%f
~kZ?e1H
而void func(int a)就没必要改成void func(const int &a); 5BM rn0
Zu ![v0
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 |zp}u (N
0fw>/"v
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 mN"g~o*
ou\~^
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; l Ztw[c
7!g4 `@!5M
=nUzBL%~
十六、extern“C”有什么作用? 'DB'lP
bl8y
o4
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 ^Zq3K
.#Lu/w' -M
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 EE~DU;p;]
-pN'r/$3V
o[k,{`M0
十七、构造函数与析构函数 7;ddzxR4
`_.(qg
派生类的构造函数应在初始化表里调用基类的构造函数; `6Yk-5
z#srgyLt
派生类和基类的析构函数应加Virtual关键字。 _sqV@ J
aB~=WWLR\
不要小看构造函数和析构函数,其实编起来还是不容易。 (+.R8
jY$3
#include <iostream.h> DP
&*P/
oN.#q$\` k
class Base ?_@Mg\Hc
,z|g b]\
{ ]]V|]}<)m
F t;[>o
public: +1#oVl!
M?8sy
virtual ~Base() { cout<< "~Base" << endl ; } v[|-`e*
zsQ]U!*rD
}; ]6(%tU
l|+$4 Nb2
class Derived : public Base $j,$O>V
5v oL@w>
{ aMu6{u6
_'!qOt7D
public: KsGW@Ho:
ZeG4z({af
virtual ~Derived() { cout<< "~Derived" << endl ; } pcv\|)&}
EkV#i
}; NcbW"Qv3
=zH)R0!eG
void main(void) )z&C&Gqz
0]f/5jvLj
{ K91O$'J
# [i3cn
Base * pB = new Derived; // upcast .Ao
_cx
R{[v#sF >#
delete pB; xjD$i'V+
[.Fm-$M-
} ^PC;fn,I
.|CoueH
输出结果为: TP| ogF?
@r<2]RXlc
~Derived J>+\a1{
Hxy=J
~Base h:7\S\|8
Gv]94$'J9
如果析构函数不为虚,那么输出结果为 vH}VieU
f/z]kfgw
~Base 'k}w|gNB
%qqCpg4
V:t{mu5j
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 pm9sI4S
P}=n^*8(I
仿止该头文件被重复引用