一、#include “filename.h”和#include <filename.h>的区别 @C5%`{\
'h{DjNSM
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 zfUkHL6
xf8.PqVNo
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 rB3b
Bzr}+J
58/\
二、头文件的作用 2Zw]Uu`sb
su Z`
加强安全检测 /S%!{;:
H=5#cPI#(^
通过头文件可能方便地调用库功能,而不必关心其实现方式 v0|"[qGb
]w9syz8X
s_`y"'^
三、* , &修饰符的位置 KnYHjJa
z';h5GNd>z
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 $dHD
w7_2JS
)"y]_}
四、if语句 A;Uw
b
Py#iC#g~
不要将布尔变量与任何值进行比较,那会很容易出错的。 IV$2`)[A&X
axd9b,
整形变量必须要有类型相同的值进行比较 ps=QVX)YP
g?!;04
浮点变量最好少比点,就算要比也要有值进行限制 7>|p_o`e
bl;v^HR0)
指针变量要和NULL进行比较,不要和布尔型和整形比较 ZQrgYeQl"
JPS<e*5
\ffU15@N
五、const和#define的比较 |-VbJd
*wJ'Z4_5F
const有数据类型,#define没有数据类型 ij1g2^],4
|}K7Q
个别编译器中const可以进行调试,#define不可以进行调试 `H\NJ,
\fD[Ej
在类中定义常量有两种方式 Jf8AKj3
tD}HL_
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; {,i='!WIm
2v\-xg%1
2、 用枚举代替const常量。 .@]M'S^1
^b(>Bg)T
}@wXm
六、C++函数中值的传递方式 DR#[\RzNI
?8)$N
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) Dv+:d 4|"
`z3"zso
void fun(char c) //pass by value BcD%`vGJ
e\>g@xE%
void fun(char *str) //pass by pointer 2E}^'o
=;HmU.Uek%
void fun(char &str) //pass by reference +v'n[xa1v
78<QNlKn
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 &0S/]E`_M
-qRO}EF
函数的类型不能省略,就算没有也要加个void j<*`?V^
<x2 F5$@
) XHcrm&
七、函数体中的指针或引用常量不能被返回 _i{4 4zE
VR0#"
Char *func(void) quw:4W>
]6 {\`a
{ E.~~.2
uu582%tiG
char str[]=”Hello Word”; B 9AE*
W4(O2RU
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 [u2)kH$
{01wW1
return str; Nm/Fc
?YbZVoD)J
} *npe]cC
A?829<
函数体内的指针变量并不会随着函数的消亡而自动释放 -d6*M*{|
&g<`i{_
Jv=G3=.
八、一个内存拷贝函数的实现体 XS/5y(W
wY j~ (P"
void *memcpy(void *pvTo,const void *pvFrom,size_t size) 7oI^sh k
OT5'c l
{ f*SAbDE
g8_IZ(%:
assert((pvTo!=NULL)&&(pvFrom!=NULL)); &vp0zYd+v
3 eFBe2
byte *pbTo=(byte*)pvTo; //防止地址被改变 ; i><03
emI]'{_G
byte *pbFrom=(byte*)pvFrom; 7eg//mL"6
L&nGjC+Lr
while (size-- >0) VCvqiHn
oWUDTio#[
pbTo++ = pbForm++; {m%X\s;ni
XP-4=0 zd
return pvTo; XOy#?X/`
4hv'OEl
} ]& qmV
%lU$;cY
RFkJ^=}
九、内存的分配方式 {L8(5
jP";ll|c
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 +<ey
Iw
Up$vBE8i]
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 k]`3if5>
[]M+(8Z_P
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 uv[e0,@
G#4cWn'
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 %j=,c{`Q
7>m#Y'ppl@
9bT,=b;
十、内存分配的注意事项 U)p P^:|
?Y~>H2
用new或malloc分配内存时,必须要对此指针赋初值。 "zO+!h'o
i4"xvLK4
用delete 或free释放内存后,必须要将指针指向NULL Bv |Z)G%RR
| JL47FR
不能修改指向常量的指针数据 ]eq3cwR[|
\0pJ+@\T9
WiL~b
=fT
十一、内容复制与比较 P
+ nT%
O ,[aL;v
//数组…… X3Vpxtb
n.y72-&v
char a[]=”Hello Word!”; AsM""x1Ix
hGF(E*
char b[10]; viBf".
2Xgw7`
!L
strcpy(b,a); D] 2+<;>`>
0nz
k?iP
if (strcmp(a,b)==0) Q_#X*I
3P p*ID
{} E4[\lX$J
9=I(AYG{m
//指针…… 6#5@d^a
\o@b5z]e
char a[]=”Hello Word!”; @11voD
?kb\%pcK
char *p; ^\mN<z(
>|7&hj$
p=new char[strlen(a)+1]; zT~ GBC-IX
1)NX;CN
strcpy(p,a); (vjQF$Hp
VPg`vI$(X
if (strcmp(p,a)==0) *(d^k;
j>R7OGg'
{} mcDW&jwQ
$b$r,mc
$X~=M_W
十二、sizeof的问题 tQJ@//C\z
+.\JYH=yEr
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节
v-[|7Pg}Z
\{+7`4g
char a[]=”Hello World!” m$hSL4N
O,JthlAV4
char *p=a; g)&-S3\
uD:O[H-x
count<<sizeof(a)<<end; //12字节 r:Cad0xj;^
Q:VD2<2
count<<sizeof(p)<<endl; //4字节 ,bmTBZV
9LJ/m\bi
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 nhXa&Nro
rmQGzQnun
void fun(char a[1000]) /yrR
f;}<O
&[\rnJ?D
{ WM=kr$/3
>o>'@)I?e6
count<<sizeof(a)<<endl; //输出4而不是1000 o
ohf))
+bf%]
} |klL KX&
6nGDoW#
rzaEVXbz1
十三、关于指针 web&M!-
bJB:]vs$
1、 指针创建时必须被初始化 =AcbX_[
9f l !CG
2、 指针在free 或delete后必须置为NULL {Y'_QW1:2
YN>#zr+~
3、 指针的长度都为4字节 ?QVD)JI*k
Cv$TNkP*
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 cS ];?tqrA
[S</QS!
char *p=new char[100]; <!OP b(g2
tg8VFH2q.z
strcpy(p,”Hello World”); 1NOz $fW
'OX6eY5
delete []p; //注意前面的[]号 J?%D4AeS]v
^<|If:|
p=NULL; qs-:JmA_w
\HK#d1>ox
5、数组指针的内容不能超过数组指针的最大容易。 :f/ p5c
^ACp_RM
如: 'pm2C6AC
(vj2XiO^+
char *p=new char[5]; dEe/\i'r9
*.nqQhW
strcpy(p,”Hello World”); //报错 目标容易不够大 @MB;Ez
v
KP<J~+_ik
delete []p; //注意前面的[]号 @Qc['V)
^jmnE.8R
p=NULL; /
V{w<
0U/:Tpyr
*iC
t4J
十四、关于malloc/free 和new /delete B-&J]H
Cq(Xa-
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 Y6D=tb
<&L;9fr
l 注意:malloc/free是库函数,new/delete是运算符 =v;-{oN!
ZA9']u%EJ
l malloc/free不能执行构造函数与析构函数,而new/delete可以 W>DpDrO4ml
+j@|D@z
l new/delete不能在C上运行,所以malloc/free不能被淘汰 M2zfN ru
h;ShNU
l 两者都必须要成对使用 "!Qhk3*
mML^kgy\N
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 ZXUe4@qfl
dl":?D4H
'g=yJ
十五、C++的特性 RD_;us@&&*
-dvDAs{X
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 `jZX(H
dIpt&nH&$
重载和内联:即可用于全局函数,也可用于类的成员函数; 'Vrev8D
/e7'5#v
Const和Virtual:只可用于类的成员函数; /t9w%Y
q/B+F%QiMQ
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 +p cj8K%
HRb_ZJz
覆盖是指派生类函数覆盖基类函数 Txfb-f!mv\
(bo bKr
函数名相同; FQ-(#[
]nQ$:%HP
参数相同; c~tSt.^WX
Czci6Lz
基类函数必须有Virtual关键字; Sm Ei _u]'
H_AV 3
;
不同的范围(派生类和基类)。 VG8rd'Z
O\D({>
隐藏是指派生类屏蔽了基类的同名函数相同 no/]Me!j=
\iL,l87
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 tm|lqa
T*{zL
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 R/Y/#X^b
Cir =(
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 Ov<3?)ok
rvmI
8
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 KOmP-q=6
,X$Avdc2
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 6Ss{+MF|v
}agl:~C
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: g-:)}8d6
kK1qFe?]
将void Func(A a) 改为void Func(const A &a)。 {&<}*4D
,m"ztu-
而void func(int a)就没必要改成void func(const int &a); O)5PUyC:H
n47=eKd70
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 r2](~&i2
8;!Eqyt
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 aW6+Up+G*
b #^aM
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; 1`}fbX;"m)
)4`Ml*7x
QhG-1P3#
十六、extern“C”有什么作用? Gzir>'d2'V
bMUIe\/v[
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 vV[dJ%
5"gRz9Ta`
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 ATzNV=2s
ZKR z=(
(k5DbP[
十七、构造函数与析构函数 wr$}AX
g_>ZE
派生类的构造函数应在初始化表里调用基类的构造函数; -oZac
wqwJpWIe
派生类和基类的析构函数应加Virtual关键字。 t@u\ 4bv
cV{ZDq
不要小看构造函数和析构函数,其实编起来还是不容易。 y{{EC#
n>E*g|a
#include <iostream.h> R_qo]WvR;
VA%"IAl
class Base Fkz
B@;)$1-UT
{ YEQW:r_h.S
&CL|q+-
public: ZM vTDH!
6|KX8\,A@
virtual ~Base() { cout<< "~Base" << endl ; } _M&.kha
bg ,}J/
}; r9M={jC
Z M+Hb_6f
class Derived : public Base {a3kn\6H0
ZmULy;{<)
{ `Q&]dE=
&1p8#i
public: bNROXiX
,OKM\N,
virtual ~Derived() { cout<< "~Derived" << endl ; } yo*iv+l
K7hf m%`N
}; }K>HS\e
~t:b<'/
void main(void) Qsntf.fT
P*PL6UQ
{ f^)uK+:.
+2zuIW.
Base * pB = new Derived; // upcast Ib2 @Wi
KCk?)Qv
delete pB; S(J\<)b
mei_aN7zW
} RGO:p]t|
A&P1M6Of
输出结果为: U R@BSK'
s\W
~Derived M?B(<j1Ri
IMGqJc,7
~Base ~B&*7Q7
pIu H*4Vz
如果析构函数不为虚,那么输出结果为 uit-Q5@~
UNQRtR/
~Base 4*vas]
be:phS4vz
-L9R&r#_e
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 ~9?U_ahfVt
Uk:.2%S2
仿止该头文件被重复引用