一、#include “filename.h”和#include <filename.h>的区别
GV28&!4sS
Aa]3jev
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 r .
(}
F2ISg'
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 z#rp8-HUDS
;>;it5 l=
"Nz@jv?
二、头文件的作用 (ss,x CF
*OIBMx#qxn
加强安全检测 I_ kA!^
n3qRt
通过头文件可能方便地调用库功能,而不必关心其实现方式 }qWB=,8HQ
Qw
}1mRv
Z",2db
三、* , &修饰符的位置 4S[)5su
?Zk;NL9
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 Q#.E-\=^
jA[")RVG
{,Rlq
四、if语句 JAI.NKB3
25j\p{*
不要将布尔变量与任何值进行比较,那会很容易出错的。 (<-m|H};
c@)?V>oe
整形变量必须要有类型相同的值进行比较 &%8IBT
}$r]\v
浮点变量最好少比点,就算要比也要有值进行限制 N93R(x)%
xU6dRjYhH9
指针变量要和NULL进行比较,不要和布尔型和整形比较 !(viXV5
!^v~hD$_q
z|Yt|W
五、const和#define的比较 Df:/r%
i1A<0W|
const有数据类型,#define没有数据类型 v-^tj}jA
|.&GmP
个别编译器中const可以进行调试,#define不可以进行调试 b&
-8/t
bd% M.,
在类中定义常量有两种方式 $bfmsCcHL
+dRRMyxe4
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; 5J1a8RBR
+Ar4X-A{y
2、 用枚举代替const常量。 F-
u"zox
<*-8E(a
m/(/!MVy
六、C++函数中值的传递方式 7Cbr'!E\_V
J#t8xL
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) $b2~H+u(
:XPat93w
void fun(char c) //pass by value ,8d&uR}x
64`l?F
void fun(char *str) //pass by pointer |"9vq<`
i~R+g3oi
void fun(char &str) //pass by reference p~""1m01,D
Sm?|,C3V
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 D ]
n|d+
rc~)%M<[2
函数的类型不能省略,就算没有也要加个void ,dw\y/dn
x K\i&A
_x#y
七、函数体中的指针或引用常量不能被返回 d6-q"
>;%QW
Char *func(void) pGy k61
w(t1m]pF[
{ JO&RuAq
w'VuC82SZ
char str[]=”Hello Word”; U5@B7v1
,j\uvi(Y
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 v0tFU!Q%
dLwP7#r
return str; 8*&73cp
)
LTV+?
} l @@pXg3
^P/OHuDL
函数体内的指针变量并不会随着函数的消亡而自动释放 w}t}Sh
mqUDve(
Fi\)ka\u
八、一个内存拷贝函数的实现体 |ITb1O`_P
@~N"MsF3
void *memcpy(void *pvTo,const void *pvFrom,size_t size) gTB|IcOs
b`^?nD7
{ 8x7TK2r
qQO*:_ezzk
assert((pvTo!=NULL)&&(pvFrom!=NULL)); \F\7*=xk
$= 2[Q
byte *pbTo=(byte*)pvTo; //防止地址被改变 v)nv"o[
{#`wW`U^
byte *pbFrom=(byte*)pvFrom; R~hIo aiN
Z?3B1o9
while (size-- >0) m(kv:5<>
R\#5;W^
pbTo++ = pbForm++; 3pL4Zhf
R[fQ$` M
return pvTo; c'Z)uquvP
TL7qOA7^X
} h^`@%g9 S
MBKF8b'k
kApD D[ N
九、内存的分配方式 8oRq3 "
ui|6ih$+
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 T?=]&9Y'
d7zZ~n
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 uk,9N
C#1'kQO
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 F{.g05^y
6cbV[!BL
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 NiE`u m
_D8 zKp
;pfN
十、内存分配的注意事项 FYefn3b
.'2I9P\!
用new或malloc分配内存时,必须要对此指针赋初值。 -~4kh]7%
2e3AmR@*
用delete 或free释放内存后,必须要将指针指向NULL -ik((qx_
<@+L^Ps~z
不能修改指向常量的指针数据 NE)w$>0M
M\7F1\ X
t
U~q4$qqE
十一、内容复制与比较 RF4B]Gqd
VsK8 :[Al
//数组…… $kMe8F_
m]
p]J_6A
char a[]=”Hello Word!”; ~HT:BO$
%(POC=b#[
char b[10]; TM_bu
-O/[c
strcpy(b,a); V2@(BliP
w+5OI9
if (strcmp(a,b)==0) iXXaB+w
Xqew~R^MP
{} jO*H8XO
r~fnK%|
//指针…… )qFqf<:yc
*p0n^XZ% ?
char a[]=”Hello Word!”; 6Iz!_
ymqn1ja1
char *p; O<Ay`p5
!/|B4Yv
p=new char[strlen(a)+1]; |q\i, }
cSG(kFQ
strcpy(p,a); > #9
a&O
dpt P(H
if (strcmp(p,a)==0) ZGCp[2$
oq1wU@n
{} l-h[I>TW
&f?JtpB
NxK.q)tj6
十二、sizeof的问题 rfSEL
57'
1L\r:mx3
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 |N
2r?b/g
gS]
char a[]=”Hello World!” 7M?Sndp$
Ip8:~Fl]
char *p=a; @j%@Z
q1r-xsjV=
count<<sizeof(a)<<end; //12字节 9fM=5
fJ\u8
count<<sizeof(p)<<endl; //4字节 q%/.+g2-\
('d,Sh
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 JlEfUg#*
Cgf4E{\U!
void fun(char a[1000]) R /_vJHI
$!z .[GL
{ P(C5@x(Z
Tpkt'|8
count<<sizeof(a)<<endl; //输出4而不是1000 )2Y]A^ Y
@KZW*-"
} EF=5[$
u
07ppq?,y
puEu)m^
十三、关于指针 ^d(gC%+!u
.O+,1&D5
1、 指针创建时必须被初始化 &/otoAr(
g0;6}n
2、 指针在free 或delete后必须置为NULL j^f54Ky.
Gs04)KJm<
3、 指针的长度都为4字节 X"HVK+
:inVwc
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 |^F$Ta
[?2?7>D8
char *p=new char[100]; u'Hh||La"
X~\O]
strcpy(p,”Hello World”); "uyr@u0b
.=hVto[QC
delete []p; //注意前面的[]号 _Vc4F_
TvRm 7
p=NULL; vn@sPT
/&c>*4)
5、数组指针的内容不能超过数组指针的最大容易。 bV#j@MJ~0
cN\_1
如: 7s}F`fjKP
1h)K3cC
char *p=new char[5]; Hbu
:HFJ!
;~`/rh
V\
strcpy(p,”Hello World”); //报错 目标容易不够大 aouYPxA`
wg:\$_Og
delete []p; //注意前面的[]号 v9t'CMU
sULsU t#
p=NULL; "`Xbi/i
YNp-A.o
W@
Ou
f \%E<
十四、关于malloc/free 和new /delete eOZ~p
8N<mV^|}
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 ,hT**(W
;2sP3!*
l 注意:malloc/free是库函数,new/delete是运算符 {q~N$"#
tejpY
l malloc/free不能执行构造函数与析构函数,而new/delete可以 F
hyY+{%
mFd|JbW
l new/delete不能在C上运行,所以malloc/free不能被淘汰 5,Co(K
jz\>VYi(7
l 两者都必须要成对使用 ,bB}lU)
YnCuF0>
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 lf R}cx
:x?G[x=
V*@&<x"E
十五、C++的特性 N7;kWQH
@TzUcE
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 t+0/$
'68#7Hs.
重载和内联:即可用于全局函数,也可用于类的成员函数; ;^)4u
[V5,1dmkI
Const和Virtual:只可用于类的成员函数; =xb/zu(
/7-FVqDx8
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 `)BZk[64
0AhUH|]
覆盖是指派生类函数覆盖基类函数 0p\Kf(|E*6
IZd~Am3f
函数名相同; A43[i@o
Kc>Rd
参数相同; p DU+(A4>
VArMFP)cz
基类函数必须有Virtual关键字; `+UBl\j
,}Im^~5
不同的范围(派生类和基类)。 |n(b>.X
'loko#6
隐藏是指派生类屏蔽了基类的同名函数相同 /c7jL4oD
(^<skx>
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 !4YmaijeN
X7MA>j3m
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 0]GenT"
<jLL2-5r0
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 /<o?T{z<-
FJW,G20L
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 R+Ug;r-[
T~?&hZ>
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 4:kDBV;v
1ZvXRJ)%
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: koj*3@\p/
gf/<sH2}
将void Func(A a) 改为void Func(const A &a)。 o$}$Z&LK
zIU6bMMT3u
而void func(int a)就没必要改成void func(const int &a); ,V;HMF.
bGlr>@;-r
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 (!Fu5m=<8
m\|EM'@k
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 aQj6XGu
}|znQ3A2\l
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; l
o-
42)
5mm&l+N)
%Bg>=C)^(1
十六、extern“C”有什么作用? 1h{7dLA
5/HkhTyj
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 QS-X_
/In=u6D O
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 DYgz;Y/%l
t^~itlE{
r[2*K 9
十七、构造函数与析构函数 R~RE21kAc
OA[fQH#{lX
派生类的构造函数应在初始化表里调用基类的构造函数; 5`::#[
* C*aH6*
派生类和基类的析构函数应加Virtual关键字。 D28>e
q$}gQ9'z'
不要小看构造函数和析构函数,其实编起来还是不容易。 *nV"X0&
OM@z5UP
#include <iostream.h> o9OCgP`Y
NezE]'}
class Base MK!Aq^Jz
mCQ:<#
{ ~/2OK!M
B}N1}i+
public: IPt
!gSp
z|$9%uz"
virtual ~Base() { cout<< "~Base" << endl ; } 'GLpSWL+*
QEF$Jx
}; \[wbJ
Ghar
hJ>v
class Derived : public Base 6E_YUk?KW
=(v'8?--
{ 65rf=*kz:
Mh@n>+IR
public: X*hPE=2`
p
s Dsq:z
virtual ~Derived() { cout<< "~Derived" << endl ; } nrbP3sf*
<2OXXQ1
}; o
ethO
RE08\gNIt
void main(void) [|(=15;
C)%qs]
{ <%=<9~e
D@c@Dt
Base * pB = new Derived; // upcast s$^2Qp
cPg{k}9Tvy
delete pB; #jPn7
caV DV
} cV4Y=
&
Fn{Pmo*rs
输出结果为: +HG*T[%/
Nc?'},
~Derived 3L{)Y`P
lA4TWU (]
~Base n`T4P$pt
@\a~5CLN
如果析构函数不为虚,那么输出结果为 U+!&~C^y
nL[G@1nR
~Base S[N9/2
"h8fTB\7S\
+R;s<pZ^
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 EIPX q
3kVN[0
仿止该头文件被重复引用