一、#include “filename.h”和#include <filename.h>的区别 "[GIW+ui
!k<+-Lf:2
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 X dB#+"[
KDQux
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 <hy>NM@$
s|,gn 5
x:l`e:`y9
二、头文件的作用 4eaC18?
4f"be
加强安全检测 VIi|:k
Sk;IAp#X9
通过头文件可能方便地调用库功能,而不必关心其实现方式 msY"Y*4
Vaq=f/
V!}, a@>p
三、* , &修饰符的位置 'd6hQ4Vw4
g4Hq<W"
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 =$BgIt
tvb hWYe
*~ &W?i
四、if语句 X:62)^~'
}doj4
不要将布尔变量与任何值进行比较,那会很容易出错的。 tanuP@O
)2^OBfl7
整形变量必须要有类型相同的值进行比较 9sE>K)
7*`ldao~
浮点变量最好少比点,就算要比也要有值进行限制 O=mGL
I}k!i+Yl
指针变量要和NULL进行比较,不要和布尔型和整形比较 B[$KnQM9Y
o~iL aN\+
*ZaK+ B
五、const和#define的比较 g_n=vO('X
PCaa_
2
const有数据类型,#define没有数据类型 t1ZZru'r
bjQfZT(
个别编译器中const可以进行调试,#define不可以进行调试 ~}ewna/2
DMs|Q$XB
在类中定义常量有两种方式 y/i"o-}}~|
2_F`ILCML
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; t 8M3VGN
W8":lpp
2、 用枚举代替const常量。 8o{ SU6pH
f"-<Z_
w$B7..r
六、C++函数中值的传递方式 **s:H'M w_
^?J:eB!
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) 1km=9[;w'
;H\,w/E9
void fun(char c) //pass by value #d|.BxH
0IA
'8_K
void fun(char *str) //pass by pointer
y"9TS,lmK
k8*=1kl"
void fun(char &str) //pass by reference 8g0& (9<)
wk5a &
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 `>#X,Lw$g
<M\Z}2 d
函数的类型不能省略,就算没有也要加个void CWDo_g$
%5z88-\
{'r*Jb0
七、函数体中的指针或引用常量不能被返回 ?$s2]}v
?2=c'%w7
Char *func(void) ^OQ_iPPI
?tSY=DK\n
{ ;w6\r!O,
BO[A1'>
char str[]=”Hello Word”; uox;PDK
]}5jX^j
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 b?y1cxTT
{'}Ofj
return str; O:Z|fDQ`
:YV!;dKJ
} xHL{3^
< )?&Jf>_
函数体内的指针变量并不会随着函数的消亡而自动释放 J J3vC
Jp,ohVRNq
Nm^q.)dO
八、一个内存拷贝函数的实现体 0`qq"j[6a
sY#K=5R
void *memcpy(void *pvTo,const void *pvFrom,size_t size) !.w S+
6U""TR!
{ qBwqxxTc
?3zx?>sG
assert((pvTo!=NULL)&&(pvFrom!=NULL)); 4l3N#U0Q
twN(]w}Ps|
byte *pbTo=(byte*)pvTo; //防止地址被改变 j`tUx#
h
em W#ZX
byte *pbFrom=(byte*)pvFrom; R0=/
Th -
T!*7G:\f"
while (size-- >0) ev@1+7(
Aw|3W ]
pbTo++ = pbForm++; '$U"RP^(
<Jvrmm[
return pvTo; .#}SK!"B
>5N}ZIN
} |mM7P^I
h\ybh
hZJ Nh,,w
九、内存的分配方式 /3c1{%B\
<w:fR|O
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 C<7J5
! TRiFD
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 B}!n6j`
97&6i TYA
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 1R:h$*-z
<T&$1 m{
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 kO9yei
CRx:3u!:
M,{F/Yu
十、内存分配的注意事项 5_i&}c23Vn
~_oTEXT^O
用new或malloc分配内存时,必须要对此指针赋初值。 }Jtaq[y\r
`}=Fw0
用delete 或free释放内存后,必须要将指针指向NULL ; 6zu!
Df4n9m}E
不能修改指向常量的指针数据 {6AJ>}3
+?L~fM69B
Wx-{F
十一、内容复制与比较 Q^F-8
ilHj%h*z
//数组…… !#?tA/t@
<
xV!vN
char a[]=”Hello Word!”; 9wwvh'T&NK
,onv
`
char b[10]; JBg>E3*N
[[|;Wr}2
strcpy(b,a); N0Y!
dG|\geD
if (strcmp(a,b)==0) npe*A
cCeD3CuRA%
{} ov+qYBuFw
\:#b9t{B-
//指针…… :kUH>O
VEn%_9(]
char a[]=”Hello Word!”; |_rj12.xo
tJn2:}-s
char *p; D\TL6"wo
Op0
#9W
p=new char[strlen(a)+1]; :V"}"{(6
+Rvj]vd}&
strcpy(p,a); 1`uIjXr(
T S.lFg:K
if (strcmp(p,a)==0) l&yR-FJ7KY
<)&ykcB
{} Jv?e?U
I2Us!W>6-
}s|v-gRM{
十二、sizeof的问题 &]M<G)9
5N6%N1
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 V:+}]"yJ,
-OHG1"/
char a[]=”Hello World!” J'7Oxjlg
7+fik0F
char *p=a; V&>7i9lEz
&sllM
count<<sizeof(a)<<end; //12字节 RHBEC@d[}
M-Js"cB[
count<<sizeof(p)<<endl; //4字节 vrbS-Z<S9
8e-{S~@W
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 bw[!f4~
1TVTP2&Rd
void fun(char a[1000]) QO,y/@Ph
B%t^QbU #\
{ HOw][}M_w
-R8RAwsLG
count<<sizeof(a)<<endl; //输出4而不是1000 Vr^wesT\Hx
'D-imLV<<
} qB&*"gf
#"Zr#P{P
}Bb(wP^B.
十三、关于指针 MHbRG_zW
4*54"[9Hr#
1、 指针创建时必须被初始化 AV'>
kz&)a>aA
2、 指针在free 或delete后必须置为NULL Uarb
[4OZ
CeZ5Ti?F
3、 指针的长度都为4字节 GM%|mFqeu
kSJWQ
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 %1 v)rg
y
X3"V1@-i4$
char *p=new char[100]; [W2p }4(
mrJQB I+
strcpy(p,”Hello World”); >WpPYUbH
XJlun l)(K
delete []p; //注意前面的[]号 ;?y?s'>t&
-1{N#c/U
p=NULL; 1"'//0
7
$+mmqc8
5、数组指针的内容不能超过数组指针的最大容易。 ctCfLlK
n*;I2 FV]
如: DB*IVg
0VbZBLe
char *p=new char[5]; FCIT+8K
"#9WF}
strcpy(p,”Hello World”); //报错 目标容易不够大 \Lc
pl-;?
>Z3}WMgBN
delete []p; //注意前面的[]号 uwIZzz
:&a|8Wi[W
p=NULL; 1{,WY(,c
*R&g'y^d
J#D!J8KP7
十四、关于malloc/free 和new /delete F;z FKvn
rdC(+2+Ay
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 9 ROKueP
:;JJvYIs
l 注意:malloc/free是库函数,new/delete是运算符 3v {GP>
1
t#Tp$
l malloc/free不能执行构造函数与析构函数,而new/delete可以 /fD)/x
_2TIan}
l new/delete不能在C上运行,所以malloc/free不能被淘汰 a-Y K*
! g}9xIL
l 两者都必须要成对使用 "+rX*~
2V
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 c XY!b=9
p?!]sO1l
2{ptV\f]D
十五、C++的特性 <:ZN
ypml22)kz
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 bg$e80
}q~A( u
重载和内联:即可用于全局函数,也可用于类的成员函数; !|`YNsR
7{b|+0W
Const和Virtual:只可用于类的成员函数; |d Soq~Vz
bG5c~
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 rL%xl,cn<
E2\)>YF{P
覆盖是指派生类函数覆盖基类函数 sd=i!r)ya
iBc(
@EJ
函数名相同; hZ%Ie%~n
K|s+5>]W/[
参数相同; =|jOio=s:
m=n
V$H
基类函数必须有Virtual关键字; aEgzQono
`yxk
Sb
不同的范围(派生类和基类)。 B'=*92i>S
fygy#&}~
隐藏是指派生类屏蔽了基类的同名函数相同 PS6G 7
1&m08dZm5
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 EKDv3aFQZ#
_o`'b80;
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 Maq{H`
n'R
8nn6^
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 .Oim7JQ8
FS']3uJ/
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 AU
>d1S.
9,F(f}(t
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 b^%4_[uRu
m@yaF:
R
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: >w
V$az
Bg34YmZ
将void Func(A a) 改为void Func(const A &a)。
D@0eYX4s
]zD/W%c
而void func(int a)就没必要改成void func(const int &a); &18} u~M
#$#{QEh0}
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 dz7*a{
O[-wm;_(=*
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 ()P?f ed
R(hqBa/V
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; 0$P40 7
id*UTY
Tg
)+ S" `
十六、extern“C”有什么作用? 2O4UytN
Ot(EDa9}IJ
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 <Q%o}m4Kt
*%g*Np_P
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 ?Bk"3{hl
fOrqY,P'
=:#$_qR
十七、构造函数与析构函数 w8>p[F5`O
JP[BSmhAV
派生类的构造函数应在初始化表里调用基类的构造函数; hNP|
a-O9[?G/x
派生类和基类的析构函数应加Virtual关键字。 k :af
x!Wl&
不要小看构造函数和析构函数,其实编起来还是不容易。 `<[Zs]Fe4
\alRBH qE
#include <iostream.h> G;,2cu
K
0;V2>!
class Base 7 +?
{KODwP'~
{ d<!bE(
Kf(% aDYq
public: 9t;aJFI
2\m+
virtual ~Base() { cout<< "~Base" << endl ; } K\o!
377$c;4F
}; pcL02W|J
R0{n0Br
class Derived : public Base :#b[gWl0Ru
#B>Hq~ vrC
{ v!40>[?|p
oXfLNe6>L
public: ,TP^i 0
Cm>8r5LG
virtual ~Derived() { cout<< "~Derived" << endl ; } _RhCVoeB
OHe<U8iu%
}; AnI ENJ
{5_*tV<I
void main(void) < R0c=BZ>
2<U5d`
{ 3"&6rdF\jB
}LQ&AIRN
Base * pB = new Derived; // upcast <gJ|Wee
llQDZ}T
delete pB; e>"{nOY4
H6*F?a`)I
} 5Sk87o1E(d
BxlpI[yWq
输出结果为: v-&^G3
5(TI2,4
~Derived Ge|caiH1I
F|Jo|02
~Base ;V`~'357%
7&OU!gp
如果析构函数不为虚,那么输出结果为 A+:K!|w
eH79,!=2
~Base [WC-EDO2lb
Ow mI*`
hDzKB))<w
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 V=.lpj9m
k45xtKS>d
仿止该头文件被重复引用