一、#include “filename.h”和#include <filename.h>的区别 ^6J*yV%
7F}I.,<W
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 9Ki86
.}Bb
:*@
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 -cY/M~
0A5xG&
"=4=Q\0PT
二、头文件的作用 'DntZK
0vQkm<
加强安全检测 "]zq<LmX
@OwU[\6fc}
通过头文件可能方便地调用库功能,而不必关心其实现方式 ,!sAr;Rk`
2HQHC]
[>C^ 0\Z~
三、* , &修饰符的位置 BN#^
/a-
mI0|lp 1$
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 ks(PH6:]<
pSV
8!
G=yQYsC$
四、if语句 Jv7 @[<$
r~t&;yRv
不要将布尔变量与任何值进行比较,那会很容易出错的。 P3lNns3
4fP>;9[F
整形变量必须要有类型相同的值进行比较 r10)1`[
mN@0lfk;
浮点变量最好少比点,就算要比也要有值进行限制 Z( xn-
V :d/;~
指针变量要和NULL进行比较,不要和布尔型和整形比较 hDmVv;M:
&,NHk9.aq
YdC:P#
Nf
五、const和#define的比较 ]S;e#u{QE
f)"O( c
const有数据类型,#define没有数据类型 "uZ'oN
8&dmH&
个别编译器中const可以进行调试,#define不可以进行调试 0Apvuf1
w5qhKu!1
在类中定义常量有两种方式 v[F_r
{(xNC#
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; 1AoBsEnd
e^Jy-?E
2、 用枚举代替const常量。 M}38uxP
^@{'! N
DrMcE31
六、C++函数中值的传递方式 w
:^b3@gd
[DjdR_9*I
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) }o)GBWqHR
(qohb0
void fun(char c) //pass by value ,:=E+sS
"#[Y[t\Ia
void fun(char *str) //pass by pointer x`C;
5%tIAbGW
void fun(char &str) //pass by reference nwO;>Qr
KwpNS(]I
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 7sHtJr
{wA@5+[
函数的类型不能省略,就算没有也要加个void ;'=!Fv
K})j5CJ/
QKCk. 0Xe
七、函数体中的指针或引用常量不能被返回 dzbzZ@y
ijyj}gpWha
Char *func(void) J5|Dduv
H+*o @0C\~
{ ]IyC
!t;$n!7<
char str[]=”Hello Word”; 3ck;~Ncj<
?bN8h)>QQ8
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 173/A=]
Q
v{q:=k
return str; siyJjE)}w
'<1T>|`/t
} C(W?)6?
IybMO5Mwn
函数体内的指针变量并不会随着函数的消亡而自动释放 yKfRwO[j
wXNFL9F8
O- r"G
八、一个内存拷贝函数的实现体 ~!)_3o
: 2?i9F0_
void *memcpy(void *pvTo,const void *pvFrom,size_t size) /6L\`\g
3n6_yK+D
{ *h-nI=
)5yZSdA
assert((pvTo!=NULL)&&(pvFrom!=NULL)); tQ=U22&7
Gi;eDrgj~
byte *pbTo=(byte*)pvTo; //防止地址被改变 f}XUxIQ-<
B8w0DJ
byte *pbFrom=(byte*)pvFrom; $:mCyP<y
x#Hq74H,
while (size-- >0) W0gaOew(^
lza'l
pbTo++ = pbForm++; 2v%~KV
GHYgSS
return pvTo; hiP^*5h
ChmPO|2F
} vK2L"e
`n5|4yaG~
"p$`CUtI
九、内存的分配方式 ]
J:^$]
jsi\*5=9p<
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 *W#x#0j
9>%f99n
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 v*3ezf\
'SOp!h$
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 ULQ*cW&;?
2}509X(*
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 P8;|>OLZ)
)+cP8$n6L
2/>AmVM
十、内存分配的注意事项 ,v)@&1Wh:
SjG=H%
用new或malloc分配内存时,必须要对此指针赋初值。 {\lu; b!
O`|'2x{[O
用delete 或free释放内存后,必须要将指针指向NULL -?'u"*#1,
m=j7 vb
不能修改指向常量的指针数据 )v
['p
uCUQxFp
Hyq|%\A
十一、内容复制与比较 C Q3;NY=o
}$iH3#E8
//数组…… *qKwu?]?>
SV8rZWJ
char a[]=”Hello Word!”; G H^i,88
PTL52+}/
char b[10]; PtmdUHvD
}bix+/]
strcpy(b,a); FV:{lC{h~
LFg<j1Gk`
if (strcmp(a,b)==0) Pme`UcE3H
3go!P])
{} rq2XFSXn
F(@|p]3*
//指针…… p,ZubRJ"
l+YpRx/T\
char a[]=”Hello Word!”; - +
$u
Mgf80r=
char *p; &)\0mpLK9
hDVD@b
p=new char[strlen(a)+1]; <\Y>y+$3
p~=%CG^5
strcpy(p,a); pm<<!`w"
}$m_):t@@
if (strcmp(p,a)==0) PO |p53
c67O/ B(
{} Ak>RLD25_
=X-$kk
0~n=|3*P
十二、sizeof的问题 ^HC!
my
iFga==rw
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 }5DyNfZ]+0
^$rt|]
char a[]=”Hello World!” V^?+|8_(
6OIA>%{
char *p=a; WY<ip<
iM}cd$r{
count<<sizeof(a)<<end; //12字节 Vs9fAAXS4
nQ/(*d
count<<sizeof(p)<<endl; //4字节 8!:4m"Y
nLo:\I(
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 1v,4[;{
N"HN]Y@w
void fun(char a[1000]) ~_^nWT*BV
2R|2yAh
{ 0/-[k
R,6?1Z:J
count<<sizeof(a)<<endl; //输出4而不是1000 EeL~`$f
MZ% P(5
} qK(?\t$
S}fIZ1
t{x&|%u
十三、关于指针 M{hA`
'4N[bRCn
1、 指针创建时必须被初始化 !cWKY\lpv
U/{cYX
2、 指针在free 或delete后必须置为NULL )RA7Y}e|m
nFxogCn
3、 指针的长度都为4字节 t%N#Yh!
%H%>6z x
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 F+c*v#T
) VJ|
char *p=new char[100]; &wLI:x5
s_EiA _
strcpy(p,”Hello World”); {^$rmwN
eQzSWn[
delete []p; //注意前面的[]号 JX>_imo
_gw~A{O
p=NULL; _(oJ8h(
bYowEzieF
5、数组指针的内容不能超过数组指针的最大容易。 RHE< QG
=Z%&jul
如: Pu}r`
E_
#!Kg?BR2
char *p=new char[5]; b"{7f
Uv5E$Y"e10
strcpy(p,”Hello World”); //报错 目标容易不够大 LTFA2X&E=
y{"8VT)
delete []p; //注意前面的[]号 TLO-$>h
8G(wYlxi
p=NULL; ;~xkT'
KA%tVBl
o2F6K*u}
十四、关于malloc/free 和new /delete coU`2n/
zXp{9P\c
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 ow]n)Te
8 I,(\<Xv
l 注意:malloc/free是库函数,new/delete是运算符 "64pVaT4
<R_3;5J%
l malloc/free不能执行构造函数与析构函数,而new/delete可以 e$Md?Pq
H|75, !<
l new/delete不能在C上运行,所以malloc/free不能被淘汰 .XYSO
QeU>%qKT
l 两者都必须要成对使用 BA
L!6
X~n Kuo
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 [ub,&j^
YwHnDVV+
T>W(Caelq
十五、C++的特性 tAYu|\]
fZXd<Fg+
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 BKV vu}V(o
9u"im+=:
重载和内联:即可用于全局函数,也可用于类的成员函数; @Q TG
Z#^2F8,]
Const和Virtual:只可用于类的成员函数; _mFb+8C
21w<8:Vg
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 I"Y?vj9]
A}[Lk#|n
覆盖是指派生类函数覆盖基类函数 7|"11^q
-XD\,y%zi
函数名相同; D`,@EW].
C^l)n!fq
参数相同; evtn/.kDR
@(Q4
基类函数必须有Virtual关键字; &X +@,!
$mp7IZE|
不同的范围(派生类和基类)。 Lf7iOW9U3
,]20I _
隐藏是指派生类屏蔽了基类的同名函数相同 x{RTI#a.
$"x(:
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 4!iS"QH?;^
oLB pG1Va
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 WMl_$Fd6
l,sYYU+iY
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 |
M-@Qvgh
0D0 #*J
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 <6-(a;T!7
6S]GSS<
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 [yjC@docH
iY.~N#Q
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: `M"b L|[R
T73saeN
将void Func(A a) 改为void Func(const A &a)。 xI_WkoI
WV?iYX!
而void func(int a)就没必要改成void func(const int &a); 9.PY49|
;41s&~eR
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 mQ' ]0D S
Z p]Bs
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 t_P1a0Zu
28Q`O$=v
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; !A!zG)Ue<
uA\A4
v }P~g
十六、extern“C”有什么作用? ;#f_e;
OJkPlDym
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 z,/dYvT<
6o6!Ol
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 h-!(O^M
eYR/kZ%<
ZOS{F_2.
十七、构造函数与析构函数 5p"*nkF
0nhsjN}v
派生类的构造函数应在初始化表里调用基类的构造函数; "P0o)g+{
z36ny o
派生类和基类的析构函数应加Virtual关键字。 GpxGDN3?
d5sGt#
不要小看构造函数和析构函数,其实编起来还是不容易。 BWw7o{d
|%zhwDQ.
#include <iostream.h> EA?:GtH
qWQJ>
class Base xZ4\.K\f]
w)DO"Z7
{ V<ODt%
T|9Yo=UK%
public: 5)&e2V',y
vP&*(WfO)
virtual ~Base() { cout<< "~Base" << endl ; } ?86h:9
Bg7?1m
}; <J`_Qc8C
{"4t`dM
class Derived : public Base 9chiu%20
AS4m227
{ a$;+-Y
:gQc@)jZ(*
public: 7e}p:Vfp
TpMfk7-
virtual ~Derived() { cout<< "~Derived" << endl ; } ?e&CbVc4
'90B),c{
}; /Tv<
l
oHeo]<Fbv
void main(void) ,{zvGZ|
MQ,$'Y5~H
{ | b@?]M
|Zkcs]8M!
Base * pB = new Derived; // upcast S7N54X2JwL
@,zBZNX
y
delete pB; $o]suF;3
dqd Qt_
} B%'Np7
zU1rjhv+
输出结果为: vi lNl|
,wZ[Y
3
~Derived ~49+$.2
4.??U!r>KI
~Base = ng\
e(!a~{(kq%
如果析构函数不为虚,那么输出结果为 mHw1n=B
;Oe6SNquT
~Base hM>xe8yE
%}$6#5"';
|fRajuA;
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 )xTp7YnZ;
Vvv
-f
仿止该头文件被重复引用