一、#include “filename.h”和#include <filename.h>的区别 |?=a84n1l
R_|Sg
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 ~0 5p+F)
TcjTF|q>
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 piv/QP-X
`$hna{e^n
%n7Y5|Uh
二、头文件的作用 3LK]VuZE
sCi"qtHP
加强安全检测 y8k*{1MuO
M`jqUg
通过头文件可能方便地调用库功能,而不必关心其实现方式 ,|u^-J@
5OS|Vp||b
xQ{n|)i>
三、* , &修饰符的位置 |yT-N3H@
_pZaVx
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 =iZj&B X
&Ub0o2+y
Nd] w I|>
四、if语句 }/cMG/%
~lSdWUk>
不要将布尔变量与任何值进行比较,那会很容易出错的。 uOU?-WtPz
WhY8#B'?
整形变量必须要有类型相同的值进行比较 ;3 |Z}P
V <;vy&&
浮点变量最好少比点,就算要比也要有值进行限制 H)u<$y!8
>^\}"dEvr
指针变量要和NULL进行比较,不要和布尔型和整形比较 BEfp3|Stb
&y~EEh|
C~PoC'"q
五、const和#define的比较 y;1
'hP&
s'Op|`&X
const有数据类型,#define没有数据类型 oI/jGyY;
LEJ8 .z6$
个别编译器中const可以进行调试,#define不可以进行调试 \8 ~`NF
;uK">L[u'
在类中定义常量有两种方式 (ZI11[e{
^ .]]0Rp&
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; g*uo2-MN&e
sh|@X\EZO
2、 用枚举代替const常量。 C OC6H'F
(w+dB8)X
~ R:=zGDV
六、C++函数中值的传递方式 N4z(2.
%M/rpEE"b%
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) UCv9G/$
XX@@tzN
void fun(char c) //pass by value EoOB0zo}Y+
`fA|])3T
void fun(char *str) //pass by pointer D. _*p
iCK p"(kf
void fun(char &str) //pass by reference U:[#n5g
Z[&7NJo(
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 E@%X
w)u6J,
函数的类型不能省略,就算没有也要加个void ED>T2.:{
bOKgR{i
,*Vt53@E
七、函数体中的指针或引用常量不能被返回 Q:/BC= ~
r'C(+E (
Char *func(void) hj8S#
'&<T;V%
{ !4ZszQg
|x[zzx#
>-
char str[]=”Hello Word”; 5m e|dvk
Ba]J3Yp,z
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 uBPxMwohR
a/(IvOy#6
return str; /%'>?8/
@fML.AT
} -5_[m@Vr
|KM<\v(A{
函数体内的指针变量并不会随着函数的消亡而自动释放 p?q~.YY
R>05MhA+
qit D{;
八、一个内存拷贝函数的实现体 2d`:lk%\
N=`xoF
void *memcpy(void *pvTo,const void *pvFrom,size_t size) AZi|85rN
>We:gKxr
{ b<N962 q$q
H+VKWGmfG
assert((pvTo!=NULL)&&(pvFrom!=NULL)); < mb.F -8
s?j` _B
byte *pbTo=(byte*)pvTo; //防止地址被改变 _ zh>q4M
.%iJin"
byte *pbFrom=(byte*)pvFrom; ~qk5Mk4$
~sd+ch*
while (size-- >0) D8b~-#
+Je(]b@
pbTo++ = pbForm++; &;D(VdSr9
@ n-[bN
return pvTo; W)0y+H\%
r
kDrqV{_
} m^O9G?
n<. T6
quvdm68
九、内存的分配方式 h kh b8zS
JMnk~8O
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 %Q0J$eC
)Apg
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 yLo{^4a.
##6_kcL:6G
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 R-8/BTls7
JpFfO<uO
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 <}^W9>u<
C#y[UM5\k;
ikSm;.
十、内存分配的注意事项 E903T' 's
2rr}5i)r|
用new或malloc分配内存时,必须要对此指针赋初值。 {APsi7HYBr
m
_0D^e7#
用delete 或free释放内存后,必须要将指针指向NULL v0ngM)^q
b0~AN#Es
不能修改指向常量的指针数据 J5J$qCJq
RawK9K_1
:OF:(,J
十一、内容复制与比较
qrFC4\q}
g' xR$6t
//数组…… q=M\#MlL0'
/<HEcB
char a[]=”Hello Word!”; $9}z^sGIM
6Q&*V7EO
char b[10]; >@2l/x8;
[I`r[u
strcpy(b,a); k{fCU%
7VF^&6
if (strcmp(a,b)==0) )-_NtMr~`!
:y?xS
{} _L6WbRu|
M NE{mV(
//指针…… ^8mF0K&
$GzTDq
Y9@
char a[]=”Hello Word!”; KPGX/l
`Z3Qx~fx
char *p; 0 L34)W
hrwQh2sm
p=new char[strlen(a)+1]; YU89m7cc'
{[~
!6&2(k
strcpy(p,a); +fgF &.
^lqcF.
if (strcmp(p,a)==0) }`oe<|
[TZlvX(E
{} y\'t{>U/
UF[2Rb8?
sckyG
十二、sizeof的问题 KfU4#2}
(c/H$'
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 nt,tM/
%$b)l?!
char a[]=”Hello World!” "t<${
@j%r6N
char *p=a; \dyJ=tg
sOSol7n
count<<sizeof(a)<<end; //12字节 &^ sgR$m
't$(Ruw
count<<sizeof(p)<<endl; //4字节 IT,TSs/Y
/t-m/&>
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 +$MNG
H61,pr>
void fun(char a[1000]) Bi"7FF(z
tylMJ$ 9*.
{ x%ZgLvdp,
qll)
count<<sizeof(a)<<endl; //输出4而不是1000 ?_e2)+q8YG
Y[AL!h
} Hno:"k?
:X>%6Xj?RV
Zho d %n3
十三、关于指针 mPNT*pAO
Do7&OBI~
1、 指针创建时必须被初始化 <RmI)g>'_^
%]JSDb=C
2、 指针在free 或delete后必须置为NULL u>Z0ug6x
Epm\=s
3、 指针的长度都为4字节 $oO9N^6yF
eRC
/Pr
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 VGoD2,(b^
#>-_z
char *p=new char[100]; )bZS0f-
Y`S9mGR#
strcpy(p,”Hello World”); +/60$60[z
j2T
Z`Z?a^
delete []p; //注意前面的[]号 mie<jha
tBgB>-h(
p=NULL; :CO>g=`
>]q{vKCAP
5、数组指针的内容不能超过数组指针的最大容易。 hKw4 [wB]
4K82%P9a
如: 4P@Ak7iL(V
^Bw2y&nN
char *p=new char[5]; '>AOJaA
|3f?1:"Z
strcpy(p,”Hello World”); //报错 目标容易不够大 \*x]xc/^
eK\1cs
delete []p; //注意前面的[]号 [HB>\
<d,Qi.G4
p=NULL; o5gt`H"
.g.v
'rJkxU{
十四、关于malloc/free 和new /delete A4.Q\0
WJ$D]7
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 * B!uYP
{J2*6_
l 注意:malloc/free是库函数,new/delete是运算符 j )6A
+E7s[9/r
l malloc/free不能执行构造函数与析构函数,而new/delete可以 -QL_a8NL
{D1"bDZ
l new/delete不能在C上运行,所以malloc/free不能被淘汰 Ml1sE,BT
`_C4L=q"
l 两者都必须要成对使用 5v4
,YHD
!|{T>yy
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 {-IH?!&v
5BCHWX*y
(J8(_MF
十五、C++的特性 Tj}H3/2
J[rpMQ
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 <zE,T@c
>K$9(
重载和内联:即可用于全局函数,也可用于类的成员函数; +^n [B
~=~|@K
Const和Virtual:只可用于类的成员函数; Sw<@u+Z;%
ftB-gItV
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 gT$`a
mGZ^K,)&OR
覆盖是指派生类函数覆盖基类函数 ZI4[v>
:@zz5MB5@
函数名相同; 7Z0fMk
mt$0p|B8
参数相同; v'(p."g
n>?o=_|uR
基类函数必须有Virtual关键字; I!?-lI@(
UU')V
不同的范围(派生类和基类)。 5Jd(&k8%
To1 .U)do
隐藏是指派生类屏蔽了基类的同名函数相同 hnag<=
LIYj__4=|
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 r9<OB`)3+
rf_(pp)
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 fB+4mEG@
$8gj}0}eH
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 x5_V5A/@LU
#?8dInu>
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 _]btsv\)f
`,|"rn#S
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 sJ[I<
U:xY~>
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: o.IJ4'}aN
e E:J
将void Func(A a) 改为void Func(const A &a)。 4SRX@/ #8*
R&Y+x;({
而void func(int a)就没必要改成void func(const int &a); ._j9^Ll
k@MAi*
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 C&Rv$<qc
T$[50~
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 w.w(*5[
YCr:nYm<f
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; 7 lc -
8UiRirw
^ Q]I)U
十六、extern“C”有什么作用? W8{g<.
/
z\wY3pIr2
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 EM9K^l`
wp7<0PP
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 [@YeQ{
Q!7il<S
A)"?GK{*
十七、构造函数与析构函数 KwO;ICdJ
jd]Om
r!
派生类的构造函数应在初始化表里调用基类的构造函数; 5Fa.X|R~
wq$+m(
派生类和基类的析构函数应加Virtual关键字。 _p0@1 s(U
c'#w 8V
不要小看构造函数和析构函数,其实编起来还是不容易。 6
axe
LsB|}_j7
#include <iostream.h> aX
CVC<l
>@?!-Fy5
class Base F/33#
U
WbF[4x
{ &c[.&L,w4
FfEP@$
public: r"HQ>Wn
hO8~Rg
virtual ~Base() { cout<< "~Base" << endl ; } 'Lm\ r+$F
7dxTyn=
}; PydU.,^7
D@.+B`bA
class Derived : public Base ;W"=s79
z)AZ:^!O
{ LC8&},iu
4WspPHj
public: \PU7,*2
Q`= ,&;T>
virtual ~Derived() { cout<< "~Derived" << endl ; } n:dnBwY
f%#q}vK-
}; 'P'f`;'_DC
":igYh
void main(void) $)or{Z$&
nulLK28q
{ M/?*?B
vca]yK<u
Base * pB = new Derived; // upcast b{
M'aV
$W_sIS0\z
delete pB; OoIs'S-Z#
4$W}6v
} (AIgW
c+a" sx\
输出结果为: yyZs[5Q
QVT|6znw
~Derived #E`wqI\'
Ec3TY<mVr
~Base r2b_$
o57r ,`N
如果析构函数不为虚,那么输出结果为 cmcR@zv
"+dByaY
~Base -K%hug
n?a?U:
>^!)G^B
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 6j2mr6o
J?y0RX
仿止该头文件被重复引用