一、#include “filename.h”和#include <filename.h>的区别 Lu@'Ee!>G
?H2{R:
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 ?pJUbZ#J
^7
oX Ju=
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 &0*=F%Fd
+`)4jx)r/
)mVpJYt;
二、头文件的作用 eQvdi|6
$yA2c^QS
加强安全检测 !?~>f>js_l
>X"V
通过头文件可能方便地调用库功能,而不必关心其实现方式 L)Iv]u
;5fq[v^P:
4dwG6-
三、* , &修饰符的位置 K^'NG!
#I(Ho:b
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 J_=42aHO
M)1?$'Aq
T8ftBIOi
四、if语句 ^5yFb=2
lB
Y "@N
不要将布尔变量与任何值进行比较,那会很容易出错的。 L~])?d
]VU a$$
整形变量必须要有类型相同的值进行比较 g,N"o72)
IfdgMELk
浮点变量最好少比点,就算要比也要有值进行限制 MSw:Ay[9
i$ :\,
指针变量要和NULL进行比较,不要和布尔型和整形比较 X( H-U
q*(
g^dPAjPQ
sZ!/uN!6
五、const和#define的比较 CI };$4W~
XvIrO]F-
const有数据类型,#define没有数据类型 C/{tvY /o
eZ^-gk?
个别编译器中const可以进行调试,#define不可以进行调试 -:|1>og
&b#O=LF
在类中定义常量有两种方式 `1eGsd,f
z`:uvEX0
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; =U_WrY<F
SqF9#&F
2、 用枚举代替const常量。 e(NpX_8
)K0BH q7r
xxN=,p
六、C++函数中值的传递方式 wwtk6;8@
mz~aSbb|
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) i9FHEu_
mar
BVFz~
void fun(char c) //pass by value eaI!}#>R+
P{-f./(JD
void fun(char *str) //pass by pointer
FB-_a
#l!Sz247
void fun(char &str) //pass by reference KF#,Q
3'H 1T
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 y~cDWD<h
*Q@%<R
函数的类型不能省略,就算没有也要加个void ^mu?V-4
>lRa},5(
_k,/t10
七、函数体中的指针或引用常量不能被返回 Z,~EH
,`3kDqS_4
Char *func(void) ;be2sTo
<opBOZ
d
{ `6.rTs$<
Wy2 pa
#Q
char str[]=”Hello Word”; S]7RGzFe
JY|f zL
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 ];.H]TIc6
Xy>+r[$D:
return str;
'7!b#if
D-[`wCa,
} St6U
YuZxKuGy
函数体内的指针变量并不会随着函数的消亡而自动释放 @GB~rfB[
XCGJ~
[a&|c%h
八、一个内存拷贝函数的实现体 jo.Sg:7&
0koC;(<n
void *memcpy(void *pvTo,const void *pvFrom,size_t size) "Yo.]PU
g?'4G$M
{ AQ>8] `e`
k|^e=I
assert((pvTo!=NULL)&&(pvFrom!=NULL)); 3}@!TI
5,0fL
byte *pbTo=(byte*)pvTo; //防止地址被改变
vj+x(
z4snH%q
byte *pbFrom=(byte*)pvFrom; V'";u?h#S
|g3a1El
while (size-- >0) F0O/SI(cA
P+m{hn~%
pbTo++ = pbForm++; Hq{i-z+
w!0`JPu
return pvTo; ZE ())W"
wgK:^DP
} 6w
d0"
h|_E>6d)
Sc!{
o!9\
九、内存的分配方式 qjsS2,wM
[dK5kO
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 GgoPwl#{
a)+;<GZ~
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 H0zKL]D'>
Fu*~{n
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 ?F@0"qi
hcvWf\4'#q
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 t,*hxzD"
jXBAo
r>=)Y32Q
十、内存分配的注意事项 \;z*j|;B
p nS{W
\Q
用new或malloc分配内存时,必须要对此指针赋初值。 >AT{\W!N
Fxu'(xa
用delete 或free释放内存后,必须要将指针指向NULL A8?uCkG
&*wN@e(c
不能修改指向常量的指针数据 @O7hY8",
0]C~CvO
O<&8gk~
十一、内容复制与比较 ZgN )sVJ
fZqMznF
//数组…… 8y-Sd\0g
+mReWf:o
char a[]=”Hello Word!”; 'WEypz
;+%(@C51GE
char b[10]; 3|=9aM^ x^
n+Ia@$|m
strcpy(b,a); nM+(
wic&
$p/%
if (strcmp(a,b)==0) }n+#o!uEf
eIzT(3(
{}
vZHm'
de?Bn+mvi.
//指针…… ]]\\Y|0
3d qj:4[f
char a[]=”Hello Word!”; ,k*g`OTW
l2)) StEm
char *p; WUQlAsme
&-Bw7v
p=new char[strlen(a)+1]; mHqw,28}
2|xNT9RW
strcpy(p,a); rZ0+mS'/G
pDGX$1O"
if (strcmp(p,a)==0) X>Cl{.
B|Y6;4?
{} (mHCK5
481SDG[b
|IbCN
十二、sizeof的问题 _5F8F4QY`
0XCtw6
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 $
e<&7
iez@j
char a[]=”Hello World!” -^m]Tb<u
29(s^#e8A
char *p=a; q[l!kC+Eh
\,<5U
F0
count<<sizeof(a)<<end; //12字节 zJnF#G
0v%ZKvSID
count<<sizeof(p)<<endl; //4字节 EgAM,\
W0n/B&C
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 o ]UG*2
|p"P+"#
void fun(char a[1000])
~yQby&s
wb@TYvDt
{ d4Y8q1
|!VSed#FSn
count<<sizeof(a)<<endl; //输出4而不是1000 ou;E@`h;x
n>d@}hyv
} 39jnoT
FL}k0
6I0G.N
十三、关于指针 *U vh;d{
!,f{I5/
1、 指针创建时必须被初始化 P&Vqr
Q/oe l'O*x
2、 指针在free 或delete后必须置为NULL ai7*</ls
Ob:}@jj
3、 指针的长度都为4字节 N/ 7Q(^
E1(2wJ-3"
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 KkVFY+/)
N"X;aVFs_
char *p=new char[100]; ?[n{M
}bQqln)#
strcpy(p,”Hello World”); ku=o$I8K
NA5AR*f'
delete []p; //注意前面的[]号 B3Id}[V
Xr54/.{&@
p=NULL; fAHK<G4
f>LwsP
5、数组指针的内容不能超过数组指针的最大容易。 l+e L:C!
Z x9oj
如: g3r4>SA
~NYy@l
char *p=new char[5]; Q;m:o8Q5
#/u% sX`#y
strcpy(p,”Hello World”); //报错 目标容易不够大 9>y6zFTV
?&Zfb
delete []p; //注意前面的[]号 9C?;'
ZeVb< g
p=NULL; 6\MH2&L<
a!Z.ZA
[yzDa:%
十四、关于malloc/free 和new /delete T~shJ0%
~&>|u5C*@
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 Gw3H1:yo
]JQ';%dne
l 注意:malloc/free是库函数,new/delete是运算符 *\9JIi 2
H5@N<v5u
l malloc/free不能执行构造函数与析构函数,而new/delete可以 RQzcsO
rQ0V3x1"Qx
l new/delete不能在C上运行,所以malloc/free不能被淘汰 o)_;cCr)q
?LP&VU1
l 两者都必须要成对使用 K!|%mI8gk
"c[ D0{\{
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 9$-V/7@)
>EQd;Af
@lo6?9oNo
十五、C++的特性 u="VJ3
3B }Oy$p
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 4wLp
<k2Qcicy
重载和内联:即可用于全局函数,也可用于类的成员函数; Y9h~ hD
~-r*2bR
Const和Virtual:只可用于类的成员函数; GEr]zMYG[A
<t9#~x#'b
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 q&.SB`
*],]E;
覆盖是指派生类函数覆盖基类函数 zLQplw`#
M"
|Mte
函数名相同; B+yr
6Q.
39s%CcI`k
参数相同; /ESmQc:DWB
yFp8 >
基类函数必须有Virtual关键字; Gy*6I)l
~HbZRDcJc
不同的范围(派生类和基类)。 O2[uN@nY
ekB!d
隐藏是指派生类屏蔽了基类的同名函数相同 >P7|-bV
FKU$HQw*
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 ^j1?L B
H-gq0+,yE
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 3Lx]-0h
S|U/m m
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 -V
Rby
t/?x#X
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 VGLE5lP X
YG<7Zv
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 }nrl2yp:%
wgm?lfX<
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: Y{]RhRR
a~b^`ykcWP
将void Func(A a) 改为void Func(const A &a)。 f_}FYeg
=Z
^=
而void func(int a)就没必要改成void func(const int &a); S^}@X?v
$<jI<vD+:
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 :-x F=Y(;
Og8:
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 |2,'QTm=
0)}bJ,5/
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; OS c&n>\t
cnh\K.*}_x
]V!q"|
十六、extern“C”有什么作用? 8$ dJh]\Y
u_.`I8qa
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 &PRu[!
I4%&/~!
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 Q<$I,C]
S:qML]RO
{}ks[%,_\
十七、构造函数与析构函数 /"d5<B `%
9OYsI
派生类的构造函数应在初始化表里调用基类的构造函数; tA?P$5?-*
> <WR]`G
派生类和基类的析构函数应加Virtual关键字。 g0@i[&A@{
`$|!h-"
不要小看构造函数和析构函数,其实编起来还是不容易。 %a-:f)@
Jq1 Zb
#include <iostream.h> }a= &o6=
/`yb75
class Base eJ0PSW/4l
I13nmI\
{ ]<D9Q>
}5#<`8
public: MW%EJT>@z
yw'b^D/
virtual ~Base() { cout<< "~Base" << endl ; } IZ /M d@C
^Xjh ?+WM
}; OyVdQ".
S5R Q
class Derived : public Base .Y.\D\>~
@C40H/dE
{ L5C4#X
\&6
public: MrIo.
|1`|E-S=
virtual ~Derived() { cout<< "~Derived" << endl ; } M%H<F3
uZ mi
}; z@hlN3dg
Yrp
WGK520
void main(void) i>gbT+*E!
GJW>8*&&(
{ :5?g<@
>U @7xeK
Base * pB = new Derived; // upcast A@^e4\
B9;dX6c
delete pB; 2[i:bksjW
D 6!`p6r+
} HpI[Af}l
x6A*vP0nm)
输出结果为: 7B
GMG|
,ZyTYD|7
~Derived <F!On5=W*
qG.HJD
~Base 9I*zgM!F
WlnmW(uahW
如果析构函数不为虚,那么输出结果为 &mj98
{<7!=@j
~Base )+2GF0%
?[Xv(60]
a5o&6 _
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 0ts]
iQ7
]Bw2> 6W
仿止该头文件被重复引用