一、#include “filename.h”和#include <filename.h>的区别 s)<#a(!
")7,ZN;
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 L f[>U
J)
v~
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 ''!pvxA
VP=(",`
WM BntB
二、头文件的作用 <Fb3\T L
70&v`"
加强安全检测 ^[XxE Lx
5gW`;Cdbyc
通过头文件可能方便地调用库功能,而不必关心其实现方式 HTI1eLZ2
c+AZ(6O?\
1&c>v3 $2
三、* , &修饰符的位置 8Q^yh6z
%JDG aG'
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 CFqoD l
=nOV!!
:7p0JGd
四、if语句 TCp!4-~,
a&)0_i:r
不要将布尔变量与任何值进行比较,那会很容易出错的。 Pgg6(O9}B^
c"t1E-Nsk
整形变量必须要有类型相同的值进行比较 BQ[1,\>
` =dD6r
浮点变量最好少比点,就算要比也要有值进行限制 {
yU1db^
.Ozfj@ f
指针变量要和NULL进行比较,不要和布尔型和整形比较 >]Hz-2b
@~fg[)7M
*=dFTd"#
五、const和#define的比较 /ee:GjUkB
"^gZh3
const有数据类型,#define没有数据类型 !zL1XW)q
^4]#Ri=U
个别编译器中const可以进行调试,#define不可以进行调试 *x[B g]/
#/@U|g
在类中定义常量有两种方式 ([UuO}m-
xBU\$ToC
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; ;OmmXygl
B{a:cz>0<
2、 用枚举代替const常量。 {f#{NA5
aGNVqS%y
nul? 5{z@
六、C++函数中值的传递方式 _~_04p
>yUThhJRn
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) dra'1E
57IrD*{
void fun(char c) //pass by value \v]}
(.P;VH9R\
void fun(char *str) //pass by pointer y&9S+
?LgR8/Io@5
void fun(char &str) //pass by reference l9)iLOj
Gk,{{:M:5
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 MLY19 ;e
>1a-}>r
函数的类型不能省略,就算没有也要加个void hxx,E>k
_`/0/69
O+`^]D7
七、函数体中的指针或引用常量不能被返回 #`:s:bwM:
2ko7t9y&
Char *func(void) ?+GbPG~
+-'qI_xo
{ C!XI0d
rfYu8-
char str[]=”Hello Word”; KoiU\r
PqPLy
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 "%urT/Fv&
F^_d8=67h
return str; /V~L:0%
mLk@&WxG
} H#k"[eZ
Ol9U^
函数体内的指针变量并不会随着函数的消亡而自动释放 f1=BBQY
>
BzF.KCScs
51.F,uY
八、一个内存拷贝函数的实现体 *]z.BZI:
V|}9d:&O
void *memcpy(void *pvTo,const void *pvFrom,size_t size) I"Ji_4QV
/`hr)
{ ' F`*(\#
84b;G4K
assert((pvTo!=NULL)&&(pvFrom!=NULL)); s6Bt)8A
NUH;GMj,,
byte *pbTo=(byte*)pvTo; //防止地址被改变 |_F-Abk
,TOLr%+v~n
byte *pbFrom=(byte*)pvFrom; seHwn'Jn
9Q]v#&1
while (size-- >0) GWjKZ1p
oHI~-{m3)
pbTo++ = pbForm++; XZcsx
uA
C:&
return pvTo; N$pwTyk
|C'w] QYm
} /2>-h-zBjw
j6Jz
Z/q%%(fh 0
九、内存的分配方式 >1pD'UZIy7
l4U& CA y
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 $2]1 3j
MGc=TQ.
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 @EfCNOy
#H
O\I7m
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 z(.$>O&6H
L)8 +/+
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 KyXgw
@EO#Ms
1a_;[.s
十、内存分配的注意事项 7b+OIZB
H!F'I)1
用new或malloc分配内存时,必须要对此指针赋初值。 )FWF T:P~
:1_hQeq
用delete 或free释放内存后,必须要将指针指向NULL =e$
#m;
zIF &ZYP
不能修改指向常量的指针数据 [w=x 0J&
bQXxb(^
-B4uK
十一、内容复制与比较 C$*`c6R
:m#vvH
//数组…… MFW?m,It)
hp-<8Mf
char a[]=”Hello Word!”; ,z1# |Y
n/$Bd FH
char b[10]; YL){o$-N"J
G8u8&|
strcpy(b,a); N#7 ]xL
1Dt"Rcn"4
if (strcmp(a,b)==0) X&wK<
4bAgbx-^
{} 3Xd+>'H
NnHwk)'
//指针…… #cdLg-v
d.2b7q09
char a[]=”Hello Word!”; |]GEJUWtCd
'0t j2
char *p; #> CN,eiZ
6\5U%~78
p=new char[strlen(a)+1]; OzO_E8Kb\
]XPGlM
strcpy(p,a); bx6@FKns}
7[D0n7B@
if (strcmp(p,a)==0) @;rVB
ykM#EyN
{} N"r ;d+LTL
_'I9rGlx3
m9L+|r
十二、sizeof的问题 H~ks"D1
lg8~`96
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 T^sxR4F
_KZ(Yq>SdY
char a[]=”Hello World!” ="A[*:hC"
}\823U
%
char *p=a; an5Ss@<4AA
4aV3x&6X
count<<sizeof(a)<<end; //12字节 Bs# #3{ylu
LL[+QcH
count<<sizeof(p)<<endl; //4字节 3\4Cg()
;euWpE;E\#
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 a@8knJ|
..~{cU4Tt
void fun(char a[1000]) z?
{#/
qWanr7n]@
{ ?5(L.XFm
9txZ6/
count<<sizeof(a)<<endl; //输出4而不是1000 Ys<wWfW
QlXy9-oJ"
} U!e4_JBR'
I[4E?
I?fE=2}9
十三、关于指针
:lE7v~!Z
&1Y+q]
1、 指针创建时必须被初始化 _p_F v>>:
3/ [=
2、 指针在free 或delete后必须置为NULL #e|eWi>
iEU(1?m2-
3、 指针的长度都为4字节 Etl7V
?BLOc;I&a
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 26Yg?:kP
{^\-%3$
char *p=new char[100]; Xs!eV
plf<O5'
strcpy(p,”Hello World”); 'P~ *cr ?A
4;*V^\',9
delete []p; //注意前面的[]号 O Z#?
`3+U6>U [
p=NULL; :w];N|48s
#ERn 8k
5、数组指针的内容不能超过数组指针的最大容易。 fk"{G>&8
lp9<j1Wl
如: 5G!X4%a
;=7z!:)
char *p=new char[5]; ~'U;).C
uZYeru"w
strcpy(p,”Hello World”); //报错 目标容易不够大 <]9MgfAe
Kz<xu ulr
delete []p; //注意前面的[]号 0)/214^&
)8<X6
p=NULL; S1+#qs{5a
.Gv~e!a8
1z`,*eD7
十四、关于malloc/free 和new /delete }UO,R~q~
}Sh-4:-D
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 ?k3b\E3
x$Dv&4
l 注意:malloc/free是库函数,new/delete是运算符 wH`@r?&
n;=A'g|Q
l malloc/free不能执行构造函数与析构函数,而new/delete可以 ?UxY4m%R;
cpy"1=K~M
l new/delete不能在C上运行,所以malloc/free不能被淘汰 iY($O/G[+
YL.z|{\e
l 两者都必须要成对使用 h49Q2`
O-B3@qQ. h
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 =&p bh
G8&'*7Bb
)s8r(.W
十五、C++的特性
F#PJ+W*h
((5zwD
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 XgbGC*dQ
wiGwN
重载和内联:即可用于全局函数,也可用于类的成员函数; ]lo1Kw
5^Y/RS i
Const和Virtual:只可用于类的成员函数; j~8+,:
Qnw$=L:
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 ~3%3{aa
U\
L"\N 7
覆盖是指派生类函数覆盖基类函数 HUghl2L.<
_qg6(
X
函数名相同; %b?Pasf.
LBE".+
参数相同; k|_2aQ02
35>}$1?-6
基类函数必须有Virtual关键字; 6a@~;!GlI
BNy"YK$
不同的范围(派生类和基类)。 4W?<hv+k7*
O<3,n;56Z
隐藏是指派生类屏蔽了基类的同名函数相同 n=&c5!
d"78:+
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 47 RY pd
zb" hy"hKw
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 Qx6/QaS?
K$.zO4
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 moR]{2Cd{
vh HMxOZ;
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 Dr1F|[
yRYWx` G
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 y#0w\/<
uaKB
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: 3wE8y&
.}E)7"Qi,
将void Func(A a) 改为void Func(const A &a)。 lP
e$AI
Z C93C7lJ
而void func(int a)就没必要改成void func(const int &a); cOb%SC[A{
9X%Klm 5w
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 @5wg' mM
K[[k,W]qb
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 .ndQ(B
@NIypi$T
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; T]W -g
8x"d/D
f*],j
十六、extern“C”有什么作用? 7j:{rCp3J
gp HwiFc
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 9qDGxW
'1
%Let AR
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 2FzS_\":I
M@ kZ(Rkv
qJA.+q.e$e
十七、构造函数与析构函数 CiuN26>
<<6w9wNon
派生类的构造函数应在初始化表里调用基类的构造函数; cnthtv+(~
?nW#qy!R
派生类和基类的析构函数应加Virtual关键字。 As|/
O7%
5B 7*Z
不要小看构造函数和析构函数,其实编起来还是不容易。 ^WD$
gd
\zU5G#LQ
#include <iostream.h> ?U08A{ c
:Y>]6
class Base _|ib@Xbin
QNXxpoS#
{ a1SOC=.M;
BUinzW z{a
public: $0}bi:7
rbPs~C-[
virtual ~Base() { cout<< "~Base" << endl ; } 'cN#rHPB6
}yw;L(3
}; YSo7~^1W"
# &83;uys
class Derived : public Base .,Qnn}:l
F5+_p@!i
{ Zk
UuniO
uR@`T18
public: Qiw4'xQm
q}$=bR1+
virtual ~Derived() { cout<< "~Derived" << endl ; } 9D{).f0
#@^w>D6W
}; gF6j6
lM^!^6=v0l
void main(void) i@5%d!J
/\cu!yiX
{ oh~
vo!
[IFRwQ^%_O
Base * pB = new Derived; // upcast X'7S|J6s
jHH
delete pB;
IB{ZE/
WV1 Z
} 6 v^
DXW?;|8)O
输出结果为: \.P}`Bpa
1lyOp
~Derived I<./(X[H:#
^r*%BUU9]%
~Base Gr$*t,ZW
nFnF_
如果析构函数不为虚,那么输出结果为 `l2<
otf%kG w
~Base =veOVv[Q&/
noNF;zT
AH'4H."o/9
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 A}bHfn|
eD{ @0&
仿止该头文件被重复引用