一、#include “filename.h”和#include <filename.h>的区别 R(83E
B~_
wLN2`ucC
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 ZV]e-
,(27p6!
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 ~!-8l&C
>DUE8hp;<
Hq\E06S@
二、头文件的作用 M|#5gKXd
*-AAQ
加强安全检测 ~1r*/@M[V
[F)/mN
通过头文件可能方便地调用库功能,而不必关心其实现方式 .S'fM]_#
]|t.wr3AU
,e FQ}&^A
三、* , &修饰符的位置 N%rL=zE
8H#c4%by)
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 Owpg]p yVD
,PMb9O\B
B/D\gjb
四、if语句 E}' d,v#Z{
n~ >h4=h
不要将布尔变量与任何值进行比较,那会很容易出错的。 +F~0\#d
iQzX-a|4]
整形变量必须要有类型相同的值进行比较 T[XP\!z]B!
\*%i#]wO@
浮点变量最好少比点,就算要比也要有值进行限制 9X$#x90
+>:}req
指针变量要和NULL进行比较,不要和布尔型和整形比较 27],O@2?L
LbX6p
aMvK8C%7
五、const和#define的比较 Dyk[ug5
CxA\yG3L&
const有数据类型,#define没有数据类型 7vpN6YP
>6[ X }
个别编译器中const可以进行调试,#define不可以进行调试 zRy5,,i5=[
Q P=[ Vw
在类中定义常量有两种方式 y+";
Qyv'nx0=
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值;
!jnqA Z
[Ql?Y$QB`4
2、 用枚举代替const常量。 Vo 6y8@\
QI#*5zm
\l]pe|0EW
六、C++函数中值的传递方式 'y6!%k*
{y&\?'L'
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) Y%)h)El
@nx}6?p\,
void fun(char c) //pass by value NB3Syl8g
XiRT|%j
void fun(char *str) //pass by pointer C9mzg
% O&m#)|
void fun(char &str) //pass by reference sUbz)BS#.
S#h'\/S
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 (~7m"?
Z<N&UFw7QJ
函数的类型不能省略,就算没有也要加个void P~\a)Szy
WS1&3mOd
prlyaq;4
七、函数体中的指针或引用常量不能被返回 G/fP(o-Wd
! 2Xr~u7a
Char *func(void) rv,NQZ
A3MZxu=':3
{ NF/Ti5y
[W9e>Nsp0
char str[]=”Hello Word”; Ld\LKwo
[%7;f|p?
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 :kb1}Wu
8<yV
return str; X;OsH
]g>m? \'n
} T/GgF&i3
\)^,PA3
函数体内的指针变量并不会随着函数的消亡而自动释放 0q[p{_t`
8tLT'2+H#
{=bg5I0|a
八、一个内存拷贝函数的实现体 ]&C:>
<78$]Z2we
void *memcpy(void *pvTo,const void *pvFrom,size_t size) Ha)3i{OM
3?.1~ "-J
{ k5aa>6K
R=vbUA
assert((pvTo!=NULL)&&(pvFrom!=NULL)); .DDg%z
ZDOF
byte *pbTo=(byte*)pvTo; //防止地址被改变 3$?9uMl#
;|>q zx
byte *pbFrom=(byte*)pvFrom; NK7H,V}T
c<=`<!FS[
while (size-- >0) 5)d,G9
[$( sUc(%
pbTo++ = pbForm++; 4_Qa=T8
y+4?U
return pvTo; s[G|q5n
Wl&
>6./{
} a^*cZ?Ta
<XQN;{xSa
AI1@-
九、内存的分配方式 t]
r,9df'
T-a&e9B
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 ^))PCn_zb
u}K5/hC
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 35Ai;mU'
aBXYri
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 ;cv.f>Cm
l |08
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 :y+B;qw
6=ZRn gQ
^M`>YOU2+
十、内存分配的注意事项 xwTijSj
`z9)YH
用new或malloc分配内存时,必须要对此指针赋初值。 LP^p~5Az
VHXI@UT*
用delete 或free释放内存后,必须要将指针指向NULL wGEWr2$
#4P8Rzl$/
不能修改指向常量的指针数据 >I$B=
K #qoR /:
:/o C:z\h
十一、内容复制与比较 { 1+Cw?1d
A",eS6
//数组…… i\t753<Ys
xS=_yO9-
char a[]=”Hello Word!”; 8weSrm
0JmFQ^g(
char b[10]; c3=-Mq9Q
,>D ja59
strcpy(b,a); 8[8|*8xqs
@%6)^]m}r
if (strcmp(a,b)==0) cC^W2\
r_b8,I6{]
{} v6wRME;JA
_*O7l
//指针…… 3p:=xL
Z5((1J9
char a[]=”Hello Word!”; ?qju
DD
d{er|$E?
char *p; u?Fnlne4@
Oo FgQEr@
p=new char[strlen(a)+1]; >vUB%OLyP
"6?lQw
e
strcpy(p,a); iaY5JEV:CA
aXMv(e+
if (strcmp(p,a)==0) CPVzX%=
ZU=,f'bU
{} r
eGm>
o^HNF+sm
Z}|TW~J=
十二、sizeof的问题 b<[jaI0
%dEB /[
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 7=}6H3|&
4HM;K_G%{
char a[]=”Hello World!” ZB-QABn
Fj
S%n$
char *p=a; ,mB Z`X@N
&|)hCJu
count<<sizeof(a)<<end; //12字节 $j57LY|r
DW#Bfo
count<<sizeof(p)<<endl; //4字节 ,Kuk_@(}5~
?N:B
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 Sa L"!uAk
+}P%HH]E/p
void fun(char a[1000]) <"<Mbbp
85'nXYN{d
{ Y=r!2u6r~
djWcbC=g_
count<<sizeof(a)<<endl; //输出4而不是1000 )D;*DUtMVm
~e{H#*f&1/
} Rq) 0i}F
JjQ8|En
T'E]
i!$
十三、关于指针 2+z1h^)W
F9-[%l
1、 指针创建时必须被初始化 uS~#4;R
T=WNBqKo]
2、 指针在free 或delete后必须置为NULL UH[<&v
uKv&7p@|_)
3、 指针的长度都为4字节 hi!`9k
qP7G[%=v
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 WJfES2N
FKC\VF
char *p=new char[100]; GD!-
qH
9 CB\n
strcpy(p,”Hello World”); _g[-=y{Bb
xOythvO
delete []p; //注意前面的[]号 t-WjL@$F/
tR1FO%nC
p=NULL; o]<jZ_|gB
vYdR ht\(
5、数组指针的内容不能超过数组指针的最大容易。 n0Go p^3
Jy]Id*u9
如: 6JhMkB^h
ygN>"eP
char *p=new char[5]; pV7N byb4
{Bh("wg$Lk
strcpy(p,”Hello World”); //报错 目标容易不够大 )>\4ULR83
!DPF7x(-{
delete []p; //注意前面的[]号 |m)kN2w
K/^
+eoW(
p=NULL; t0q_>T-kt
OiF{3ae(
i\)3l%AK]T
十四、关于malloc/free 和new /delete =Q-k'= 6\
);Z]SGd
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 2:Q(Gl`<l
;\qXbL7
l 注意:malloc/free是库函数,new/delete是运算符 P>(P2~$Y"
*:g_'K"+
l malloc/free不能执行构造函数与析构函数,而new/delete可以 VevNG*
Fi4UaJ3K
l new/delete不能在C上运行,所以malloc/free不能被淘汰 rFey4zzz
A?8\Y{FQ
l 两者都必须要成对使用 *t(4 $
v8m`jxII64
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 ?sXG17~Bm
iCP~O
Pz%~ST
十五、C++的特性 a[sKE?
9cG<hX9`F
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 ^]>aHz9
%D`o
重载和内联:即可用于全局函数,也可用于类的成员函数; !77NG4B
)MSZ2)(
Const和Virtual:只可用于类的成员函数; +6l]] *H
H=p`T+
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 /1d<P! H
"UG
K8x
覆盖是指派生类函数覆盖基类函数 &J$##B
Qqc]aVRF
函数名相同; <^8*<;PaG
4r&f%caU
参数相同; XN#&NT{t}
+BL{@,zr
基类函数必须有Virtual关键字; +Rwx%=
[|RjHGf
不同的范围(派生类和基类)。 (RE2I
_Zc4=c,K
隐藏是指派生类屏蔽了基类的同名函数相同 w<NyV8-hL
booRrTS
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 .TpsJXF
M:n 6BC>t"
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 [/|zH'j:
=sgdkAYwP
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 <41ZZ0<EwY
NmpnJu|8
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 [=uIb._Wv
eg<pa'Hw
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 TTZe$>f
V'pqxjfd
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: </[: 9Cl
8 lT{1ro
将void Func(A a) 改为void Func(const A &a)。 },@``&e
(=u'sn:s
而void func(int a)就没必要改成void func(const int &a); 94/BG0
3<:jx~y>
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 eSfnB_@x2
Y@uh[aS!
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 )C~9E 5E
Z[?mc|*x
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; e,0-)?5R
h4)Bs\==mT
[XR$F@o
十六、extern“C”有什么作用? :TalW~r|
np9dM
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 MYdO jcN
56}X/u
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 h8{(KRa 6
B&0;4
2C=Q8ayvX
十七、构造函数与析构函数 @'6"7g
/=: j9FF
派生类的构造函数应在初始化表里调用基类的构造函数; nw6pV%
=9wy/c$
派生类和基类的析构函数应加Virtual关键字。 WsGths+[
%, P>%'0
不要小看构造函数和析构函数,其实编起来还是不容易。 R2<s0l
w@-M{?R
#include <iostream.h> xHA0gZf
Fc 6iQ
class Base 'b&yrBFD
3=mr
"&]r:
{ 8LzBh_J?
u<xo/=Z
public: !l@zT}i??
P-`(0M7^
virtual ~Base() { cout<< "~Base" << endl ; }
9+=gke
u]*0;-tz
}; % Zjdl
<0P5 o|
class Derived : public Base d+eZub94U
}UwO<#
{ tc+WWDP#"
sD;M!K_
public: a_~=#]a
k[j90C5
virtual ~Derived() { cout<< "~Derived" << endl ; } zUJZ`seF
<y.]ImO
}; ;&b.T}Nf06
b97w^ah4gJ
void main(void) qet>1<
8^/I>0EZ
{ X}ma]
WJH\~<{mP
Base * pB = new Derived; // upcast !]yO^Ob.E
c2nKPEX&5
delete pB; zAzP,1$?
&ANP`=
} n2B){~vE
')Y'c
输出结果为: MGS-4>Q#
yw-8#y
~Derived r!1D*v5&:
%QmxA
7fW
~Base Zdc63fllM
W,5Hx1z R
如果析构函数不为虚,那么输出结果为 W !w, f;
s$ENFp7P
~Base EOj"V'!
\_V-A f{6
/P|fB]p
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 dO> VwP
'7^M{y/dU
仿止该头文件被重复引用