一、#include “filename.h”和#include <filename.h>的区别 $Xz9xzOR
zMtK_ccQ
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 k[Uc_=
% OiSuw
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 z6'zNM7M
GE~mu76%
v[m/>l2[P
二、头文件的作用 qh F/iUE
:Nc~rOC_
加强安全检测 &giJO-^
f
1v`<Vb%"}T
通过头文件可能方便地调用库功能,而不必关心其实现方式 I+`~6
! ~&X1,l1*
1mI)xDi9
三、* , &修饰符的位置 7:M%w'oR
6],5X^*Y
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 "~d)$]+
7zR7v
/MQd [03]
四、if语句
Q9%N>h9
q G=`'%,m
不要将布尔变量与任何值进行比较,那会很容易出错的。 xiA9X]FB
`Ph4!-6#
整形变量必须要有类型相同的值进行比较 8.Y6r
m&2<?a}l
浮点变量最好少比点,就算要比也要有值进行限制 KkAk(9Q/3
r(cS{oni
指针变量要和NULL进行比较,不要和布尔型和整形比较 q3scz
y3;G<9K2c]
[2)Y0; ["
五、const和#define的比较 )vuxy
3.R?=npA
const有数据类型,#define没有数据类型 &h4(lM
r<&d1fM;X
个别编译器中const可以进行调试,#define不可以进行调试 ;zSh9H
1!vR
8.
在类中定义常量有两种方式 )JuD !
s`H}NjWx
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; <bGSr23*
Eg
w ?
2、 用枚举代替const常量。 9-bDgzk
Fm [,u
g<UjB
六、C++函数中值的传递方式 m:p1O3[R
]d% hU
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) 17<\Q(YQ=
)5&w
void fun(char c) //pass by value lg1?g)lv
p(U'c}@2
void fun(char *str) //pass by pointer tgg*6lc
z4{|?0=C
void fun(char &str) //pass by reference JRU)AMMU&
(MNbABZQ
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 J,+|
Fb
pmQ9iA@=
函数的类型不能省略,就算没有也要加个void ]'T-6
+uv]dD*i
,pf<"^li
七、函数体中的指针或引用常量不能被返回 AbLOq@lrK
Du[$6
Char *func(void) 8Jxo;Y
|3"'>*
J
{ #p=/P{*
#XC\=pZX
char str[]=”Hello Word”; roW8 4x
+s1mm c
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 a7OD%yQ
p jHUlQ
return str; ivw2EEo,
=AZ>2P
} v0=^Hym
~{U~9v^v(
函数体内的指针变量并不会随着函数的消亡而自动释放 ur*1I/v
S
G]e^%i
#Du1(R
八、一个内存拷贝函数的实现体 ,}`II|.oB
8n);NZ
void *memcpy(void *pvTo,const void *pvFrom,size_t size) ]hL 1qS
N55;oj_K
{ p0'A\@|
XP6R$0yN
assert((pvTo!=NULL)&&(pvFrom!=NULL)); $S=lm {
!*+~R2&b
byte *pbTo=(byte*)pvTo; //防止地址被改变 DghX(rs_
K~v"%sG{`
byte *pbFrom=(byte*)pvFrom; A[=)Zw
"
9$UjZ$ v
while (size-- >0) >JrQS"[u
7(Y!w8q&^
pbTo++ = pbForm++; K^s!0[6
?sp
return pvTo; ihf5`mk/$
6D3fkvcZ
} qK;n>BTe
gWgYZX
m3P%E8<Q#
九、内存的分配方式 RK"dPr
ZZzf+F)T
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 ?&"cI5-
fLct!H3
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 D|`[ [
!u>29VN
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 6-QTqb?U;N
J3y5R1?EP
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 ,R ]]]7)+
r?[PIf
`m@ 06Q
十、内存分配的注意事项 4+' yJ9~,B
552c4h/T
用new或malloc分配内存时,必须要对此指针赋初值。 >vt#,8VAN
5JIa?i>B
用delete 或free释放内存后,必须要将指针指向NULL Ny
p5=
Gvl-q1PVC
不能修改指向常量的指针数据 li%=<?%T
!|!:MYn
HQ ^> ~
十一、内容复制与比较 BLuILE:$
pkjL2U:
//数组…… p,$1%/m
a?M<r>
char a[]=”Hello Word!”; $2 ~A^#"0
g9'50<|J
char b[10];
VG q'
}bAd@a9>3
strcpy(b,a); >bEH&7+@_'
\SA5@.W
if (strcmp(a,b)==0) T_y 'cvh
) ?+-Z2BwA
{} dkLc"$(O
o/2\8
//指针…… &}YB!6k h^
MU-ie*+
char a[]=”Hello Word!”; bx!Sy0PUJ
:sk7`7v
char *p; ol:,02E&
?U iwr{Q
p=new char[strlen(a)+1]; "Yq-s$yBi
V.: a6>]
strcpy(p,a); XDz![s
r/Qq-1E
if (strcmp(p,a)==0) H.v`JNs(
()}O|JL:K
{} 3Ey#?
?b^VEp.;}
>"5^]o2?~l
十二、sizeof的问题 "7l p|0I
$ 6Nm`[V
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 Czid"Ih-
rm1R^n
char a[]=”Hello World!” WK:~2m&y
f/eT4y
char *p=a; DTlM}
lk1c2
count<<sizeof(a)<<end; //12字节 MDGcK/$')f
v}+axu/?
count<<sizeof(p)<<endl; //4字节 Haaungb"
` {k>I^Pg
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 F2AM/m^!q
p! zC
void fun(char a[1000]) h"
P4
/>FrMz8;(
{ z%`Tf&UL
V4l`Alr\L
count<<sizeof(a)<<endl; //输出4而不是1000 &!N5}N&
;6e#W!
} (|bMtT?"x
slOki|p;
gD@ &/j7
十三、关于指针 eW1$;.^
NQ'^z
1、 指针创建时必须被初始化 E@JxY
]6pxd \Q
2、 指针在free 或delete后必须置为NULL y~SFlv36
{iYu
x;(
3、 指针的长度都为4字节 DcQ^V4_
J=
ia
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 _B8e1an
Y
H
2iV
char *p=new char[100]; --Dw
S/G,A,"c
strcpy(p,”Hello World”); ?\<2*sW [k
!6@xX08z
delete []p; //注意前面的[]号 Bag2sk
69dFd!G\
p=NULL; v@XQ)95]F
h:z;b;
5、数组指针的内容不能超过数组指针的最大容易。 2 8f-8B
1_fFbb"
如: bv\V>s
#Vs/1y`()
char *p=new char[5]; ^n@iCr9
-102W{V/T
strcpy(p,”Hello World”); //报错 目标容易不够大 Jj fNH
~
u5H#(&Om
delete []p; //注意前面的[]号 `RthX\Tof
N5}vy$t_P
p=NULL; d%t]:41=Z
mIFS/C
>u*woNw(XM
十四、关于malloc/free 和new /delete yx{Ac|<mR
wju~ 5
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 ,*E%D _
x3PeU_9
l 注意:malloc/free是库函数,new/delete是运算符 tPO.^
>h[tHM
O
l malloc/free不能执行构造函数与析构函数,而new/delete可以 ~e
6yaX8S
6ynQCD
l new/delete不能在C上运行,所以malloc/free不能被淘汰 ~<v{CBq[
~-']Q0Z
l 两者都必须要成对使用 ^nbze
+GP"9S2%R
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 v
0rX/ mj
AA>5h<NM
.7ahz8v
十五、C++的特性 ;cp-jY_U
&0(2Z^Z>fw
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 4 3]6J]!)
^>%=/RX
重载和内联:即可用于全局函数,也可用于类的成员函数; :Jhx4/10
GVn9=[r
Const和Virtual:只可用于类的成员函数; W.MJyem
A'[A!NL%
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 aI8wy-3 I
lmH!I)5
覆盖是指派生类函数覆盖基类函数 |i|YlWQS
OUI}jJw+
函数名相同; M#<x2ojW
;lYO)Z`3\
参数相同; /R|"/B0
MYN1zYT6j
基类函数必须有Virtual关键字; @'C)ss =kj
7MoO2
不同的范围(派生类和基类)。 :6HMb^4
`d
OjCA_&
隐藏是指派生类屏蔽了基类的同名函数相同 -\UzL:9>
/jj!DO#
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 JSGUl4N
(/ k, q
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 Q=^}B}G
)B}]0`z:P
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 A8Jbl^7E+
.*Hv^_
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 J,7_5V@jJ
'O{hr0q}
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 n8:2Z>
SCGQo.~,
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: !Id F6 %
tmb0zuJ&C!
将void Func(A a) 改为void Func(const A &a)。 zEO
9TuBO
'kx{0J?
而void func(int a)就没必要改成void func(const int &a); #e8CuS
3J(STIxg
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 Ei}DA=:s
8De
`.!Gg
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 D(h|r^5
?nt6vqaV
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; w~Y#[GW
jBE=Ij
JBoo7a1
十六、extern“C”有什么作用? X0!48fL*
u[dI81`
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 q5HHMHB
0hNc#x6
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 2l\Oufer"
>Zr/U!W*?
VFYJXR{
十七、构造函数与析构函数 0f-gQD
,%,}[q?]d
派生类的构造函数应在初始化表里调用基类的构造函数; C}00S{nAZ
~&yaIuW<
派生类和基类的析构函数应加Virtual关键字。 Eydk645:3
ol:_2G2xQ
不要小看构造函数和析构函数,其实编起来还是不容易。 ^3r2Q?d\
WrG)&&d
#include <iostream.h> kXOlZC
eA+6-'qN
class Base tGf
PMTyiwlm
{ }NYsKu_cM
W0nRUAo[
public: xknP
`T
?VzST }
virtual ~Base() { cout<< "~Base" << endl ; } 7M$>'PfO
|bBYJ
}; TnKe"TA|9
9xWeVlfQ
class Derived : public Base kj-Sd^
YHAy+S
{ \y0abxIHS
X GO_n{x
public: >yL8C:J9
YL{LdM-xM
virtual ~Derived() { cout<< "~Derived" << endl ; } w-\GrxlbX
Qb SX'mx<
}; Uh9$e
IPY@9+]
void main(void) aIm\tPbb
G,$jU9 f
{ WJg?R^
"4ovMan
Base * pB = new Derived; // upcast D&]SPhX
q'1rSK
delete pB; v4 c_UFEh<
~s88JLw%&u
} 0_%u(?
yuhSP{pv'
输出结果为: jLZ~9FXF2
PR.?"$!D{
~Derived ^(a %B
j[c|np4k\
~Base JA1(yt
q5QYp
如果析构函数不为虚,那么输出结果为 a|66[
*,z__S$Q)
~Base }t]CDa_n
f4:gD*YT
6{1c
S
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 jMZ{>l.v
QZzi4[-as
仿止该头文件被重复引用