一、#include “filename.h”和#include <filename.h>的区别 gbMA-r:IC
{EZR}N
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 !Mw/j`*
v^eAQoFLhN
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 ir'<H<t2
i?B<&'G
5%D`y|
二、头文件的作用 | K|AUI
&</)k|.A6\
加强安全检测 O$z"`'&j#
RV@B[:
通过头文件可能方便地调用库功能,而不必关心其实现方式 Vw;iE=L
G739Ne[gL
MY{Kq;FvRP
三、* , &修饰符的位置 g Nz
skeeec\V
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 y:\<FLR}j
9V)cf
#U0| j?!D
四、if语句 hcU^!mp
HpbwW=;V
不要将布尔变量与任何值进行比较,那会很容易出错的。 yVzV]&k
/7B3z}rd
整形变量必须要有类型相同的值进行比较 2G|}ENC
bLl
?!G.
浮点变量最好少比点,就算要比也要有值进行限制 `Zp*?
bZSt<cH3
指针变量要和NULL进行比较,不要和布尔型和整形比较 )j]f
]8
B_#M)d
O
y-@`3hYM@
五、const和#define的比较 $lB!Q8a$
%Lx#7bR U
const有数据类型,#define没有数据类型 rG-x 3>b
e8SAjl"}
个别编译器中const可以进行调试,#define不可以进行调试 k=t{o
1_&W1o
在类中定义常量有两种方式 hRKJKQ@7
M+-odLltw
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; |@rf#,hTDp
b7'A5]X
2、 用枚举代替const常量。 "kt7m
-iy17$
4J9Y
六、C++函数中值的传递方式 9-#=xE9'U
DbI)tDi5D
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) 9u^za!pE
% T$!I (L&
void fun(char c) //pass by value 0kp{`3ce
N#OO{`":Z`
void fun(char *str) //pass by pointer CW@EQ3y0
{Y+e|B0
void fun(char &str) //pass by reference G #$r)S
*wdNZ
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 k:U%#rb;
t:'^pYN:g
函数的类型不能省略,就算没有也要加个void lE bV)&'
Rs]Y/9F;{
06af{FXsGb
七、函数体中的指针或引用常量不能被返回 2j^8{Agz
]o9^?iU]
Char *func(void) #3C]"
~c,+)69"T
{ /KgP<2p
p1s&
y0:d
char str[]=”Hello Word”; {bNKyT
!J}Q%i
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 G7#<Jo<8
|3EKK:RE
return str; `g'9)Xf4KT
8(@(G_skp
} J.,7d ,
yD^Q&1
函数体内的指针变量并不会随着函数的消亡而自动释放 ;3O=lo:$~
CVgVyy^
35#"]l"
八、一个内存拷贝函数的实现体 h"$],=
/n 1H;~f]
void *memcpy(void *pvTo,const void *pvFrom,size_t size) Y7@$#/1
m@`
NN
{ &(X-b"2
!X{>?.@~
assert((pvTo!=NULL)&&(pvFrom!=NULL)); *46hw(L
VL@eR9}9K
byte *pbTo=(byte*)pvTo; //防止地址被改变 `yua?n
^14a[ta/'
byte *pbFrom=(byte*)pvFrom; R|t.JoP9
.^FdO$"
while (size-- >0) j
!rQa^
MryY<s
pbTo++ = pbForm++; iriF'(1
wb (quu
return pvTo; gO]jeO
lZhd^69y
} ,mvU`>Ry
Jbqm?Fy4X
wD`jks
九、内存的分配方式 gK>aR ^*
~g|z7o
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 5(&'/U^
~e<h2/Xc
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 >_LZD4v!<
iz\GahK
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 ycSC'R
-|3feYb'
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 Qj',&b
v?qU/
s&~i S[
十、内存分配的注意事项 4ROuy+Ms'
8k
-l`O~
用new或malloc分配内存时,必须要对此指针赋初值。 gOKF%Ej31T
>]S-a-|Bp
用delete 或free释放内存后,必须要将指针指向NULL 4n,>EA85
7xy[;
不能修改指向常量的指针数据 Avn)%9
!1cVg
ls|
S{F'k;x/5
十一、内容复制与比较 )xj!7:n)
eg
Zb)pP
//数组…… r*XEne
S"G`j!m1
char a[]=”Hello Word!”; &d/x1=
2qxede
char b[10]; k9vzxZ%s:
T+U,?2nF:
strcpy(b,a); Tkf
JC|6
W$ag
|WV
if (strcmp(a,b)==0) Q%
LQP!Kg
OX[pK_:`l
{} =UMqa;\K
[/IN820t
//指针…… 7\nR'MOZ
P{gy/'PH,
char a[]=”Hello Word!”; nb ,+!)+
w_lN[u-L
char *p; Vp
j[)W%L
%1^E;n
p=new char[strlen(a)+1]; N!iugGL
@_4E^KgF
strcpy(p,a); 5
i;n:&Y
UG:S! w'
if (strcmp(p,a)==0) 5`H.{4@
J.^%VnrFO9
{} E[kf%\
Os>^z@x
D3xyJ
十二、sizeof的问题 IP=."w
D +Ui1h-
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 w9Z,3J6r
yON";|*\m
char a[]=”Hello World!” H". [&VP5Z
?f'iS#XL
char *p=a; 9~ JeI /
0AWOdd>.
count<<sizeof(a)<<end; //12字节 ! uX0G4
|];f?1
count<<sizeof(p)<<endl; //4字节 .qAlPe L:
`_Fxb@"R
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4
0V[`zOO(o
VS
?n pH
void fun(char a[1000]) ~H1ZQ[
K 0Gm ?(
{ xq-TT2}<L
9XEP:}5,
count<<sizeof(a)<<endl; //输出4而不是1000 5vo5t0^o
_Z{EO|L
} )g
; !IL
_(1Shm
FBGe s[,
十三、关于指针 !)-)*T
fs,]%g^
1、 指针创建时必须被初始化 &@rXt!
On*pI37(\
2、 指针在free 或delete后必须置为NULL 'Tbdo >y
ScCA8JgY
3、 指针的长度都为4字节
A\:u5(
J@l QzRqRb
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 @/f'i9?oM`
$LOwuvu>
char *p=new char[100]; KbTd`AIL
(mOL<h[)IP
strcpy(p,”Hello World”); EV.F/Wh
Ahf71YP
delete []p; //注意前面的[]号 oGvk,mh"(
E -+t[W
p=NULL; sEzl4I
G<:gNWXd\
5、数组指针的内容不能超过数组指针的最大容易。 H9%[!
RF
1<;RI?R[9
如: ,+GS.]8<
/mG-g%gE
char *p=new char[5]; G(;R+%pu
8.ej65r*
strcpy(p,”Hello World”); //报错 目标容易不够大 ;6}> Shs
ifI0s)Pn
delete []p; //注意前面的[]号 7KJ%-&L^
d.xT8l}sS
p=NULL; UZRN4tru6
DI0Wk^ m
>J) 9&?
十四、关于malloc/free 和new /delete tUT:vK`
`R
m<1
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 j.kv!;Rj=
Mb:>
l 注意:malloc/free是库函数,new/delete是运算符 9Yhlq$;g
M4)Y%EPc
l malloc/free不能执行构造函数与析构函数,而new/delete可以 P!u0_6
C8KV<k
l new/delete不能在C上运行,所以malloc/free不能被淘汰 BG_6$9y
6%Pvh- ~_
l 两者都必须要成对使用 U8OVn(qV
_[h!r;DsG
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理
G *
=>
}CM#jN?(
d+p^fBz
十五、C++的特性 q{l %k
lUIh0%O
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 7QdboEa
yG2rAG_G&
重载和内联:即可用于全局函数,也可用于类的成员函数; d>O/Zal
v;#0h7qd
Const和Virtual:只可用于类的成员函数; C:.>*;?7
Q})&c.L
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 Y-+JDrK
_wUg+Xs]
覆盖是指派生类函数覆盖基类函数 z\-/R9E/5-
V ;"Rp-`^
函数名相同; X*M2 O%g`L
-s^)HR
l
参数相同; JC#5CCz
tA^CuJR
基类函数必须有Virtual关键字; U~w8yMxX
b+$E*}
不同的范围(派生类和基类)。 3Xm>
3
&q +l5L"
隐藏是指派生类屏蔽了基类的同名函数相同 8On MtP
fo~>y
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 R`M@;9I.@
v >s,*
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 a,h]DkD
#u3E{NB
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 7bQST0 ?
>z73uKA(
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 T(Ji%S>
%CQv&d2
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 .\:MB7p
bX
6uGu
7
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: v6ei47-
^%0^DN
将void Func(A a) 改为void Func(const A &a)。 yq[.
WPve
iNilk!d6Q3
而void func(int a)就没必要改成void func(const int &a); yb,$UT"]
iUs_)1
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 '(-H#D.oy'
J>"qeR
/
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 +No` 89Y
Gd$!xN%O
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; KwgFh#e
m'M5O@?
AR{$P6u!%|
十六、extern“C”有什么作用? r;p@T8k
/PbMt
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 0sH~H[ap
!s:_>P`MQ
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 V+r&Z<&
)l.AsfW%
FL4BdJ\
十七、构造函数与析构函数 E!uQ>'iq.
e,d}4 jy
派生类的构造函数应在初始化表里调用基类的构造函数; K_k'#j~*?
<[w5M?n8
派生类和基类的析构函数应加Virtual关键字。 M Np4=R
/%gMzF
不要小看构造函数和析构函数,其实编起来还是不容易。 lM#,i\8Q
&%g$Bi,G
#include <iostream.h> N1$PW~)Y
] ^?w0A
class Base G6lC[eK
].2t7{64
{ j<`3xd'
l]j;0 i
public: j-VwY/X
h<bhH=6~
virtual ~Base() { cout<< "~Base" << endl ; } j\zlp
/^v!B`A@
}; {:3:GdM6
PKC0Dt;F.
class Derived : public Base r;"D>IM\
_1mpsY<k
{ FBvh7D.hV
U$3DIJVI
public: &5XEjY>@
SlHDBr!.z
virtual ~Derived() { cout<< "~Derived" << endl ; } f=VlO d
u&[L!w
}; 7U?#Xi5
+6$-"lf
void main(void) ew~?&=
uA;#*eiA/
{ <QC7HR
cvE)
Base * pB = new Derived; // upcast Qe-Pg^PS]
pKGhNIj$
delete pB; 4:^MSgra
,zr,>^v
} {2mF\A#.
R4P&r=?
输出结果为: uK`gveY
G-|c%g!ejf
~Derived S=.%aB
<2L,+
~Base |)" y
ryw%0H18
如果析构函数不为虚,那么输出结果为 GQk/ G0*&
eThFRU3 F
~Base "Nb2[R
GDe,n
QBH|pr
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 /5z,G r
<DPRQhNW]
仿止该头文件被重复引用