一、#include “filename.h”和#include <filename.h>的区别 [=Xvp z
g%K3ah
v
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 JWLQ9UX
;(z0r_p<q
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 c Mq|`CM
iKu5K0x{>I
|KuH2,n0
二、头文件的作用 Zvc{o8^z
\hg12],#:@
加强安全检测 cEe>Lyt
xSw ^v6!2
通过头文件可能方便地调用库功能,而不必关心其实现方式 oC[$PPqX#
+?%huJYK,
'C(YUlT2?P
三、* , &修饰符的位置 X4jtti
!y6
D+<k*]
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 Rt+s\MC^r
1|2X0Xm{
(i {
四、if语句 xR$xAcoSB
1Eh(U
不要将布尔变量与任何值进行比较,那会很容易出错的。 dH8H<K~
9T)-|fja_
整形变量必须要有类型相同的值进行比较 }psJ'aiG*
.Ir 5gz
浮点变量最好少比点,就算要比也要有值进行限制 RK|C* TCnl
m!g
f!
指针变量要和NULL进行比较,不要和布尔型和整形比较 lOql(ZH`w
b?y3m +V`
u\50,N9Wp{
五、const和#define的比较 =YR/|9(
9\V^q9l
const有数据类型,#define没有数据类型 }yUZ(k#
XJ.vj+XXb
个别编译器中const可以进行调试,#define不可以进行调试 <Dl7|M
Wfp[)MM;
在类中定义常量有两种方式 [8<)^k
iJU]|t
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; %;GDg3L[p
/aP`|&G,)
2、 用枚举代替const常量。 DvU(rr\p
^MuO;<<,.
:hZYh.y\l
六、C++函数中值的传递方式 op;OPf,
"Q^Ck7
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) '(;`t1V8k
h60*=+vdJ
void fun(char c) //pass by value 4\3Z$%2^LZ
|*Hw6m
void fun(char *str) //pass by pointer <yBZsSj
N\rbnr
void fun(char &str) //pass by reference _8S!w>$)
NeQ/#[~g
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 0:Xvch0
>A#]60w.
函数的类型不能省略,就算没有也要加个void Fe}Dnv)}Z
(z\@T`6`
%+qD-{&
七、函数体中的指针或引用常量不能被返回 }PD?x4
8e x{N3
Char *func(void) Iell`;
K%O%#Kk
{ _uID3N%
{U>B\D
char str[]=”Hello Word”; Y$shn]~
?(H/a-(:v}
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 fM6Pw6k
Ab/gY$l
return str; J;HkR9<C
eVS6#R]'m
} 5?{a=r9
V^[o{'+
函数体内的指针变量并不会随着函数的消亡而自动释放 ;~3CuN8
9ELLJ@oNC
abp]qvCV
八、一个内存拷贝函数的实现体 GG-7YJ
`;L>[\Xi
void *memcpy(void *pvTo,const void *pvFrom,size_t size) JdF;*`_7*
Y:XE4v/)@L
{ 1ve
%xF
HTAJn_
assert((pvTo!=NULL)&&(pvFrom!=NULL)); D:4Iex9$F"
N[:;f^bH49
byte *pbTo=(byte*)pvTo; //防止地址被改变 vWc =^tT
NJRk##Z
byte *pbFrom=(byte*)pvFrom; akoK4!z
+iY .Y V
while (size-- >0) R.-2shOE'
Kf/1;:^
pbTo++ = pbForm++; fYBmW')
07`hQn)Gc
return pvTo; &Ba` 3V\M
$hXhq*5|c
} PRg^E4
&'Pwz
rOHU)2
九、内存的分配方式 J'jwRn
kr[p4X4
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 ux:czZqy
tNj-~r
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 mII7p LbQ
`83s97Sa
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 d0vn/k2I
~PAF2
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 2dg+R)%
'B>fRN
AwN7/M~'
十、内存分配的注意事项 LlKvi_z
ji9 (!G
用new或malloc分配内存时,必须要对此指针赋初值。 I?r7dQEm
r)E9]"TAB
用delete 或free释放内存后,必须要将指针指向NULL N8S!&*m
9.)*z-f$
不能修改指向常量的指针数据 Z]OXitt7
Myaj81
o_R<7o/d|
十一、内容复制与比较 Oh)s"f\N
++1<A&a
//数组…… vkUXMMuf+e
?tx%KU\3
char a[]=”Hello Word!”; >U.
$=3&qg"!
char b[10]; 7/C,<$Ep
/Y|y0iK
strcpy(b,a); lOB*M!8
,41Z_h
if (strcmp(a,b)==0) wiHGTaR
>v--R8I *
{} M uz+j.0
@/jLN
//指针…… !'scOWWn
?'SHt9b3|
char a[]=”Hello Word!”; B6 rz
"u^%~ 2
char *p; f"i(+:la
Lxz!>JO>
p=new char[strlen(a)+1]; c$fi3O
cC@.&
strcpy(p,a); D#"BY;
J
A)v!
{
if (strcmp(p,a)==0) IDCuS
}Rl^7h<!
{} F9h'.{@d
J5Pi"U$FkY
^jY/w>UdH
十二、sizeof的问题 FVY$A=G
b~$B0o)
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 $r> $
u
Qg9*mlm`
char a[]=”Hello World!” 3%HF" $Gg
n@1;5)&k~
char *p=a; q-?
k=RX`
8d4:8}
count<<sizeof(a)<<end; //12字节 4sJM!9eb[
e8E*Urtz
count<<sizeof(p)<<endl; //4字节 ;zq3>A
fyHFfPEE
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 }enS'Fpf`
/w[B,_ZKTk
void fun(char a[1000]) "&9L
@bfW-\ I
{ Jr2x`^aNO
(_2Iu%F
count<<sizeof(a)<<endl; //输出4而不是1000 $4YyZ!_.@
_T\/kJ)Q\
} Q5K<ECoPk
/xS4>@hn
t?&@bs5~g
十三、关于指针 Xgb ~ED]
d;:H#F+ (
1、 指针创建时必须被初始化 7tZvz `\
XHN*'@
77;
2、 指针在free 或delete后必须置为NULL $!Qv f
[B0]%!hFw
3、 指针的长度都为4字节 mE>v (JY
#k}x} rn<'
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 6I8A[
E8gbm&x*
char *p=new char[100]; ^k#.;Q#4
fCMFPhF
strcpy(p,”Hello World”); heizO",8.&
bh
Nqj
delete []p; //注意前面的[]号 f52*s#4}
9>QGsf.3
p=NULL; Gl!fT1zh0
l^~E+F~
5、数组指针的内容不能超过数组指针的最大容易。 \jR('5DcB
}Cs.Hm0P
如: r}>q*yx:
Tr\6AN?o
char *p=new char[5]; 3AQu\4+A
a ](Jc)
strcpy(p,”Hello World”); //报错 目标容易不够大 t%k1=Ow5i
.,vF%pQ
delete []p; //注意前面的[]号 M94zlW<
F]qX}
p=NULL; #&$a7L}
Q$`u=-h|
\gU=B|W
十四、关于malloc/free 和new /delete g %ZKn
2SABu796j
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 s:p6oEQ=J
@nNhW
l 注意:malloc/free是库函数,new/delete是运算符 M9PzA'}4W6
Id(wY$C&>
l malloc/free不能执行构造函数与析构函数,而new/delete可以 M~!DQ1u
S7(Vc H
l new/delete不能在C上运行,所以malloc/free不能被淘汰 s.uw,x
0b3z(x!O
l 两者都必须要成对使用 l<DpcLX
g!![%*'
b
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 q8=hUD%5C
#Rw9Iy4
^.Xom~
十五、C++的特性 *LA2@9l
'F .tOD
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 !et[Rdbu
Fcp8RBq
重载和内联:即可用于全局函数,也可用于类的成员函数; <H]1 6
+G.F'
Const和Virtual:只可用于类的成员函数; RZL:k;}5
+`(,1L1
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 $qp,7RW
;,&$ob*/
覆盖是指派生类函数覆盖基类函数 `A0trC3
|to|kU
函数名相同; I_aSC 4
gX'nFGqud
参数相同; \v,mr|
%=PGvu
基类函数必须有Virtual关键字; "TQ3{=j{
T+knd'2V6
不同的范围(派生类和基类)。 _oU}>5
i0jR~vF
{B
隐藏是指派生类屏蔽了基类的同名函数相同 QRw/d}8l
>cdxe3I\
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 wF\5 X
QE\t}>
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 7%7 \2!0J}
y]YUuJ9a
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 PKK18E}{%^
%=G*{mK
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 qiyX{J7Z
OtsW>L@ O(
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 }$wWX}@
>P_/a,O8
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: [m+):q^
QKAt%"1&
将void Func(A a) 改为void Func(const A &a)。 ? 3'O
W&'[Xj
而void func(int a)就没必要改成void func(const int &a); ;5.S"
M~SbIk<#a<
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 z{uRqAG
YB?5s`vr9d
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 up^D9(y\
1 Vq)& N
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; pf%B
o
00(\ -eb
R>CIEL
十六、extern“C”有什么作用? 6
h%%?
\[CPI`yQe
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 C\RJ){dk
qTV;L-
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 i p"LoCE
yr"BeTrS.
wusj;v4C4M
十七、构造函数与析构函数 QGkMT+A
PQJI~u9te}
派生类的构造函数应在初始化表里调用基类的构造函数; ='U>P(
R-
56JvF*hP
派生类和基类的析构函数应加Virtual关键字。 G Ch]5\
-&UP[Mq
不要小看构造函数和析构函数,其实编起来还是不容易。 by0@G"AE+
kbcqUE
#include <iostream.h> 9irT}e
%j7HIxZh
class Base jVxX! V
lq[o2\
{ UFOUkS
F
lBN1OL[N
public: \YN(rD-
WA1h|:Z
virtual ~Base() { cout<< "~Base" << endl ; } (h$[g"8
Z H1UAf
}; Q}qw`L1
9=FqI50{
class Derived : public Base K|Kc.
M0$wTmXM
{ #eZm)KFQg
[i 7^a/e
public: Zp'q;h_
K>_~zW nc
virtual ~Derived() { cout<< "~Derived" << endl ; } `COnb@uD
]@G$L,3
}; 5 52U~t
`rQDX<?
void main(void) QswbIP/>:'
Lo-\;%y
{ =e j'5m($3
_O w]kP='
Base * pB = new Derived; // upcast .`;
bQh'!
F&[MyX U4
delete pB; "%[a Wb
|u5Xi5q.f
} T x
6\
\fjr`t]
输出结果为: P"k`h=>!4
x } X1
O)
~Derived VQe@H8>3
5U[bn=n
~Base nbf w7u
1:Dm,d;
如果析构函数不为虚,那么输出结果为 ~V`F5B
%'vLkjI.
~Base 27CVAX ghV
898=9`7e
\'[C_+;X
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 5<=ktA48[
S)L(~N1
仿止该头文件被重复引用