一、#include “filename.h”和#include <filename.h>的区别 C5,fX-2Q
?'9IgT[*
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 d%"XsbO
LzNfMvh
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 Cl]?qH*:
%dFJ'[jDL
Qop,~yK
二、头文件的作用 v/.'st2%
f,KB BBbG
加强安全检测 cN8Fn4gq
Z,A $h>Z
通过头文件可能方便地调用库功能,而不必关心其实现方式 dQ.#8o=
\`2'W1O
t'l4$}(
三、* , &修饰符的位置 MmR6V#@:
r(46jV.sD:
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 L2ydyXIsd
K+F"V W*?
_!@:@e)yB{
四、if语句 zqo0P~
p;w&}l{{
不要将布尔变量与任何值进行比较,那会很容易出错的。 +*:mKx@Nw
d*0RBgn
整形变量必须要有类型相同的值进行比较 VNHceH
8b)WOr6n
浮点变量最好少比点,就算要比也要有值进行限制 JhFbze>
-}|L<~
指针变量要和NULL进行比较,不要和布尔型和整形比较 KBmO i
%
D
O
{1" I
五、const和#define的比较 iM)K:L7d
:_~.Nt
const有数据类型,#define没有数据类型 3k`Q]O=OU
LV^^Bd8Ct
个别编译器中const可以进行调试,#define不可以进行调试 d8wVhZKI"
&aLTy&8Fv
在类中定义常量有两种方式 ~Ld5WEp k3
, ~O>8VbF
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; Yi*F;V
&>,;ye>A
2、 用枚举代替const常量。 ctZ,qg*N
,,gMUpL7_8
}kqh[`:
六、C++函数中值的传递方式 3ic /xy;}
*9^8NY]
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) ahg:mlaob
6]?mjG6
void fun(char c) //pass by value 3' i6<
P1Hab2%+
void fun(char *str) //pass by pointer wtY)(ka
*c$[U{Px
void fun(char &str) //pass by reference EfrQ~`\
,Vhve'=*2
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 ayy\7b
?e$&=FC0;
函数的类型不能省略,就算没有也要加个void Q[biy{(b8
L0fe
rx1u*L
七、函数体中的指针或引用常量不能被返回 9&n9J^3L
ub-3/T
Char *func(void) [a2]_]E%
""0Y^M2I
{ q!y. cyL
mgAjD.
char str[]=”Hello Word”; P}v
;d]
u2 s
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 pAE
(i7
yV(#z2|
return str; 79v +ze
,|:.0g[n
} qzUiBwUi@
*#T:
_
函数体内的指针变量并不会随着函数的消亡而自动释放 k83K2>]
HAxLYun(3w
mr\,"S-`
八、一个内存拷贝函数的实现体 |nefg0`rk
(,U|H`
void *memcpy(void *pvTo,const void *pvFrom,size_t size) i%K6<1R;y{
3^7+fxYWo
{ EZ)b E9
An.
A1y
assert((pvTo!=NULL)&&(pvFrom!=NULL)); K%v:giN$l`
D$hQ-K
byte *pbTo=(byte*)pvTo; //防止地址被改变 J:@gmo`M;V
)D+BvJ Y"
byte *pbFrom=(byte*)pvFrom; Lv%3 jj
{N4 'g_
while (size-- >0) 8;@y\0
>n"0>[:4
pbTo++ = pbForm++; *7xcwjeP
oy^-?+
return pvTo; l=CAr
XV]N}~h o`
} 72dRp!JU
z
&EDW5I
@]l|-xGCWn
九、内存的分配方式 Q,3kaR@O
Q,KNZxT,q
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 u cpU$+
>v+1v
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 a
!VWWUTm?
ip-X r|Bq
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 |a{;<a
Nny*C`uDF
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 q\EYsN</;
!mlfG"FE
jY=y<R_oK
十、内存分配的注意事项 J&A1]T4d
L7rgkxI7k*
用new或malloc分配内存时,必须要对此指针赋初值。 ZmsYRk~@-
&=[!L0{
用delete 或free释放内存后,必须要将指针指向NULL MQoA\
duG!QS:
不能修改指向常量的指针数据 qp})4XT v
&-=~8
JwSF}kNs}
十一、内容复制与比较 g *Js4
Cbff:IP
//数组…… 5#.m'a)
Jt8;ddz
char a[]=”Hello Word!”; t2dsYU/
KuJ)alD;1
char b[10]; }4C_r'd6
S_P&Fv
strcpy(b,a); <=.6Z*x+
%'KRbY
if (strcmp(a,b)==0) \?n6l7*t>
Nc\DXc-N
{} *Jsb~wta
k{ qxsNM
//指针…… ,Cr%2Wg-
$s7U
|F,I
char a[]=”Hello Word!”; >Sc yc-n
t%qep|
char *p; _.s,gX
Qt.*Z;Gs
p=new char[strlen(a)+1]; s5*4<VxQN.
spa:5]B
strcpy(p,a); ,JwX*L<:
ED` 1)1<
if (strcmp(p,a)==0) 7KIekL
y0xBNhev
{} ~0PzRS^o
>$m<R&
_Raf7 W
十二、sizeof的问题 hz:7W8
~@'wqGTp
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 +xYu@r%R
YS|Dw'%g /
char a[]=”Hello World!” 2y`h'z
IWo'{pk
char *p=a; _[6sr7H!
W8& )UtWQ
count<<sizeof(a)<<end; //12字节 edL2ax
M(C">L]8
count<<sizeof(p)<<endl; //4字节 );!ND%
.n7@$kq
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 s{^B98d+W
sQgz}0_=)
void fun(char a[1000]) zH1;h
X_78;T)uA
{ J1w[gf]J
bSe\d~{
count<<sizeof(a)<<endl; //输出4而不是1000 'w,gYW
i:YX_+n
} 5t%8y!s
Fip
5vrD
1]/;qNEv
十三、关于指针 WWpMuB_G
3k'Bje?9~
1、 指针创建时必须被初始化 JU)^b
V_
LuySa2,
2、 指针在free 或delete后必须置为NULL s~OcL 5
=w3A{h"^
3、 指针的长度都为4字节 ^iONC&r
0`E G-Hw
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 ]njNSn
mh8fJ6j29N
char *p=new char[100]; aL:|Dr3SX
LAC&W;pJ"
strcpy(p,”Hello World”); !yv>e7g^
cAN!5?D\
delete []p; //注意前面的[]号 Z]Bv
P^OmJ;""D
p=NULL; W.^zN' a
#ZJ 1\Ov
5、数组指针的内容不能超过数组指针的最大容易。 >N#Nz
0|(
g**!'T4&o
如: MFROAVPZ5
@aQ:3/
char *p=new char[5]; :a{dWgN
_;3,
strcpy(p,”Hello World”); //报错 目标容易不够大 K/zb6=->
zr!7*,
p
delete []p; //注意前面的[]号 93*d:W8Vr
s~{rC{9X
p=NULL; <eXGtD
bse`Xfg
j4;^5
Dy^
十四、关于malloc/free 和new /delete "73*0'm
0J+WCm`
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 S${%T$>
C<_\{de|9
l 注意:malloc/free是库函数,new/delete是运算符 xT 06*wQ
;+DEU0|pe
l malloc/free不能执行构造函数与析构函数,而new/delete可以 ^`!+7!
(9`dLw5
l new/delete不能在C上运行,所以malloc/free不能被淘汰 deAV:c
}W^@mi
l 两者都必须要成对使用 W(]A^C=/
kSV(T'#x
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 _".h(
rCF=m]1zxT
g)6>=Qo`8E
十五、C++的特性 (kR
NqfX
\0~?i6o
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 rf=l1GW
n{N0S^h
重载和内联:即可用于全局函数,也可用于类的成员函数; E2M<I;:EA
)5( jx
Const和Virtual:只可用于类的成员函数; \lG) J0
C<=rnIf'
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。
%.d.h;^T
m]V#fRC
覆盖是指派生类函数覆盖基类函数 CF>&mXg\
Y/J~M$9P,
函数名相同; =Fc]mcJ69
[\3ZMH
*
参数相同; 'dWUE-
)Lz
=[e
基类函数必须有Virtual关键字; =RHtugwy
!:xycLdfUp
不同的范围(派生类和基类)。 i!%WEHPe
w)ki<Dudg
隐藏是指派生类屏蔽了基类的同名函数相同 ng/h6
S
Q~(Qh_Ff
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 w<H2#d>5!@
w=]A;GgA
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 y7/4u-_c
JOG-i
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 [;{xiW4V]
uD(C jHM>
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 G>"n6v'^d
6~sU[thGW
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 M@KQOAzt
+F q_w
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: l 7uTk5
YCE *Dm
将void Func(A a) 改为void Func(const A &a)。 $VQ;y|K+[
DTH}=r-
而void func(int a)就没必要改成void func(const int &a); p>eYi \'
+%j27~R>D
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 / fUdb=!Z
3|!3R'g/ >
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 EC5= 2w<
XY{N"S8
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; ?,x\46]>_K
lusUmFm'*
Pk;/4jt4
十六、extern“C”有什么作用? $}vzBuWHwN
g4k3~,=D3
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 Y!45Kio
Z$INmo6
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 q)9n%- YgP
2FaCrc/
fZpi+I
十七、构造函数与析构函数 J:"@S%gy%
Q>Klkd5(
派生类的构造函数应在初始化表里调用基类的构造函数; /&|p7
. q
-:3b
派生类和基类的析构函数应加Virtual关键字。 Odwf7>
9QX!HQ|5y8
不要小看构造函数和析构函数,其实编起来还是不容易。 I4%kYp]
e YP^.U)
#include <iostream.h> 3O;H&
1K#[Ef4
class Base OqS!y(
(
!&Q?AS JH
{ "P?O1
s<"|'~<n
public: i`e[Vwe2x@
ROn@tW
virtual ~Base() { cout<< "~Base" << endl ; } iJE:>qOTD5
{
i6L/U.
}; uvJHkAi
tz2=l.1
class Derived : public Base mWYrUI
]QHp?Ii1
{ LI@BB:)[
#8M?y*<I
public: 9#7W+9
yYGs]+
virtual ~Derived() { cout<< "~Derived" << endl ; } ~C^:SND7
#<==7X#
}; \,Ws=9f
3QBzyJWf
void main(void) ,ja!OZ0$
[/q
Bvuun
{ sQA_ 6]`
MvZa;B
Base * pB = new Derived; // upcast L,.~VNy-
BFw_T3}zn
delete pB; {e|.AD
d'Bxi"K
} 8#JX#<HEo
TW>GYGz
输出结果为: UH6 7<_mK
9vyf9QE;
~Derived UL}wGWaoG
&~+QPnI>Pm
~Base VO eVS&}
\8$~ i
如果析构函数不为虚,那么输出结果为 ;PC!
"P#1=
~Base izcaWt3 a
XX/s@C
-t S\
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 :,JjN&
BVeMV4
仿止该头文件被重复引用