一、#include “filename.h”和#include <filename.h>的区别 Ll6|Wh X
!bD`2m[Q
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 A?OaP
3Q(#2tL=
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 9Lxa?Y1
\c$!C8z
`_&7-;)i*\
二、头文件的作用 yn5yQ;
"(#]H;!W
加强安全检测 jJCd2O]
ul3._Q
通过头文件可能方便地调用库功能,而不必关心其实现方式 zpd Z.
ng[ZM);
l<RztzUw
三、* , &修饰符的位置 wrW768WR
O>`DR0
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 9y"*H2$#
!pLQRnI}6
ra k@oW]
四、if语句 m48m5>
K%A:W
不要将布尔变量与任何值进行比较,那会很容易出错的。 {wx!~K
E7qk>~Dg
整形变量必须要有类型相同的值进行比较 NrdbXPHceN
pTlNJ!U>
浮点变量最好少比点,就算要比也要有值进行限制 cvvba 60
\{[Gdj`
指针变量要和NULL进行比较,不要和布尔型和整形比较 Rc H",*U
~vIQ-|8r:
O=PyXOf
五、const和#define的比较 7a}vb@
2!b+}+:
const有数据类型,#define没有数据类型 C.
Hr
\j]i"LpWb
个别编译器中const可以进行调试,#define不可以进行调试 P'6eK?
ZVj/lOP X
在类中定义常量有两种方式 @m[r0i0J"
A~6:eappH
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; 2\M^_x$N
("k.5$
2、 用枚举代替const常量。 lXS.,#lp
X
rVF
%
xFt[:G`\}u
六、C++函数中值的传递方式 2R2ws.}
rn7eY
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) ,=tPh4>
i5sNCt
void fun(char c) //pass by value W4Ey]y"
1>1&NQ#}
void fun(char *str) //pass by pointer )Fh+6
=Vv"\p8
void fun(char &str) //pass by reference db%o3>>e
]E\o<"#t/
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 )B86
xG JX~)
函数的类型不能省略,就算没有也要加个void B\,pbOE?#
+,&8U&~`
Qx-/t 9`!Z
七、函数体中的指针或引用常量不能被返回 _s/5oRHA
ab5 a>w6}
Char *func(void) 5J^S-K^r
0>?%{Xy
{ I'Dc9&2
:nZVP_d+
char str[]=”Hello Word”; LE!xj 0
2 5DXJb^:
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 $[L~X
M
M<R3Jz T
return str; ,Q8[Ur?G
1PD{m{
} #)&kF+
/gWaxR*m
函数体内的指针变量并不会随着函数的消亡而自动释放 'O%itCy)
KTr7z^
)YE3n-~7{
八、一个内存拷贝函数的实现体 F<K;tt
,@mr})s
void *memcpy(void *pvTo,const void *pvFrom,size_t size) 3mI(5~4A]?
YIjY?
{ W rB:)Q(8=
CatbEXO
assert((pvTo!=NULL)&&(pvFrom!=NULL)); J:<mq5[
cZB?_[Cp
byte *pbTo=(byte*)pvTo; //防止地址被改变 dux.Z9X?
TR;" &'#k
byte *pbFrom=(byte*)pvFrom; 5G$N
<$6r1y*G
while (size-- >0) z l?Gd4
|\/`YRg>
pbTo++ = pbForm++; ]S@zhQ
<'n'>@
return pvTo; k!?sHUAj
S$~T8_m^U
} Y fRjr
&8p]yo2zO
'%Cc!63t*
九、内存的分配方式 LqNt.d @
Yatd$`,hW
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 dY=]ES}`
cQg:yoF
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 E}?n^Zf
Y~E
8z
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 * {avx
B* 0TM+
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 JRti2Mu
-!o*A>N
voX4A
pl
十、内存分配的注意事项 (,nQ7,2EX
=Msr+P9Ai
用new或malloc分配内存时,必须要对此指针赋初值。 ,>
Ya%;h2k
wh Hp}r
用delete 或free释放内存后,必须要将指针指向NULL
2:5Go
k)j6rU
不能修改指向常量的指针数据 "SMRvi57T
Nm{+!}cC
^LI\W'K
十一、内容复制与比较 e1<9:h+
$jkzm8{W
//数组…… V; pRw`
83(-/y
char a[]=”Hello Word!”; 7sX#6`t
^;8dl.;
char b[10]; $?Km3N\?v
i C)+5L#'
strcpy(b,a); b6%[?k
.8%&K0
if (strcmp(a,b)==0) ,+P2B%2c
2y"L&3W
{} ;NoiH&
/wi*OZ7R
//指针…… _^Z
v[P
9kzJ5}
char a[]=”Hello Word!”; awU!3)B
`uwSxt
char *p; r@t
\a+
+B '<0
p=new char[strlen(a)+1]; $x/VO\Z{-
sC'PtFK8z
strcpy(p,a); l5T0x=y9!
&q7}HO/ @
if (strcmp(p,a)==0) BCmKzv
YB+My~fw{l
{} ,Mr_F^|
Vl^p3f[
u0Bz]Ux/Q
十二、sizeof的问题 gJH^f3
L9]y~[R:
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 'WNq/z"X
no$X0ia
char a[]=”Hello World!” J[{ R:l\
< ZG!w^
char *p=a; v t_lM
TV Zf@U
count<<sizeof(a)<<end; //12字节 "]bOpk T
s7(1|}jh
count<<sizeof(p)<<endl; //4字节 |;(>q
}U^iVq*
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 Q 5&|1m Pb
|fB/ hs \
void fun(char a[1000]) nGM;|6x"8|
)b~+\xL5J
{ rMoz+{1A
+3k.xP?QS
count<<sizeof(a)<<endl; //输出4而不是1000 E#E&z (G2
$3S`A]xO
} @8Cja.H
8{
+KNqz
0Q~\1D 9g
十三、关于指针 L@S1C=-/
}ww`Y
1、 指针创建时必须被初始化 "H9q%S,FH
OWp`Wat
2、 指针在free 或delete后必须置为NULL #bS}?fj
`k7X|
3、 指针的长度都为4字节 7ju^B/7
*Oq&g\K)
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 q>6RO2,
Ekn3ODz,
char *p=new char[100]; KP`Pzx
:<H4hYt2
strcpy(p,”Hello World”); h^YUu`P
T3Sz<K$E
delete []p; //注意前面的[]号 v=daafO
y~z&8XrH
p=NULL; Ih[k{p
tqpSir
5、数组指针的内容不能超过数组指针的最大容易。 &"=O!t2
N"7BV
如: L/)eNZ
I0N~>SpZ5
char *p=new char[5]; hb(H-`16
^[6#Kw&E
strcpy(p,”Hello World”); //报错 目标容易不够大 ./<giTR:p
y"iK)SH
delete []p; //注意前面的[]号 5'[yw:P-8
8g?2( MT;
p=NULL; R ^"*ut
a :CeI
Pk6_ 1LV
十四、关于malloc/free 和new /delete w6ck wn,
z`YAOhD*h4
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 _`Dz%(c
p::`1
l 注意:malloc/free是库函数,new/delete是运算符
`ghNS
ItE)h[86
l malloc/free不能执行构造函数与析构函数,而new/delete可以 (e32oP"
(hIe!"s*
l new/delete不能在C上运行,所以malloc/free不能被淘汰 miV 8jaV
A{wk$`vH
l 两者都必须要成对使用 +D?Re%HI
]sqp^tQ`e
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 [9Hrpo]tU:
w ; PV
&M
KssIoP
十五、C++的特性 LbnF8tj}h
ig'4DmNC
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 U\q?tvn'J
R+Rb[,m
重载和内联:即可用于全局函数,也可用于类的成员函数; f.RwV+lq
^mZTki4
Const和Virtual:只可用于类的成员函数; lAAP V
+}C M2>M
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 OKCX>'j:S
zU#
OjvNk
覆盖是指派生类函数覆盖基类函数 HqA3.<=F,
nVk]Qe
函数名相同; gWy2E;"a
J|b:Zo9<f"
参数相同; 9-?kamA
&uJ7[m19z
基类函数必须有Virtual关键字; :LB< z#M
7P DD
不同的范围(派生类和基类)。 #~ [mn_C
@TnAO8Q>XD
隐藏是指派生类屏蔽了基类的同名函数相同 mGUl/.;yp-
~wd~57i@
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 :w4I+*]
Zx,aj
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 Jm}zit:o
]TKM.[[
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 ?[q.1O
rVx?Yo1F'
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 0 }aw9g
a<{+
JU5
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 cH$Sk
;AgXl%Q
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: h2edA#bub
V~qlg1h
将void Func(A a) 改为void Func(const A &a)。 V %Rz(a+c
!yX4#J(
而void func(int a)就没必要改成void func(const int &a); L}%4YB
>a1ovKF
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 ic|>JX$G
^7%
KS
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。
y-CVyl
Nh|QYxOP
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; eEkbD"Q
w`OHNwXh#I
EYF]&+ 9
十六、extern“C”有什么作用? k`Ifd:V.y
+']S
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 FzGla} )
ur2`.dY>3"
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 D>Ph))QI
+Udlt)H
.EUOKPK4W
十七、构造函数与析构函数 y|@=j~}Zq
UZ+FV;<
派生类的构造函数应在初始化表里调用基类的构造函数; +EBoFeeIG
/0H39]y!~
派生类和基类的析构函数应加Virtual关键字。 8TnByKZz
oLp:Z=
不要小看构造函数和析构函数,其实编起来还是不容易。 `Z0#IeX=
#5x[Z[m
#include <iostream.h> -3T6ck
*u%4]q
class Base ?pv}~>
B[0XzV]Z
{ KwiTnP!Dca
G&Sp }
public: >K9uwUi|b]
W@x
UR-}51
virtual ~Base() { cout<< "~Base" << endl ; } Gm.n@U p
43Yav+G(+
}; eOQUy+
:d<;h:^_
class Derived : public Base mSzBNvci
&@xixbg
{ QpPJ99B|
~a5p_x P
public: aMFUJrXo
]64mSB
virtual ~Derived() { cout<< "~Derived" << endl ; } )[>b7K$f
Z?5kO-[
}; 8vM}moper
V(Ps6jR"BS
void main(void) -zd*tujx
v 6?{g
{ qlSc[nEk
$3sS&i<
Base * pB = new Derived; // upcast _e=R[
sSi1;9^o
delete pB;
5eO`u8M
g@.RfX=
} #s1O(rLRl
~: f9,
输出结果为: 31y=Ar""
+!V*{<K
~Derived V$+xJ m
i=-zaboo
~Base Wr7^
RV|: mI
如果析构函数不为虚,那么输出结果为 !p1OBS|
E{d Mdz
~Base DEaO=p|
#{GUu',?&
|*7uF<ink6
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 U%ce0z
d^IOB|6Q
仿止该头文件被重复引用