一、#include “filename.h”和#include <filename.h>的区别 ~T9%%W[
G0Smss=K
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 oJbD|m
wIz<Y{HA=
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 .a1WwI
P
Ig)h-w?
_ro^<V$%
二、头文件的作用 8Br*
(m4`l_
加强安全检测 2Otd
W)ihk\E
通过头文件可能方便地调用库功能,而不必关心其实现方式 sH(4.36+
r.0IC*Y
Q\ TawRK8
三、* , &修饰符的位置 /<vbv
3 :X3n\z
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 m+||t
7R[4XQ%
nellN}jYsM
四、if语句 ByoSwQ
}(z[
rZ
不要将布尔变量与任何值进行比较,那会很容易出错的。 6uW?xB9
,J"6(nk
整形变量必须要有类型相同的值进行比较 O&Q_vY
rlmzbIuI9
浮点变量最好少比点,就算要比也要有值进行限制 +',[q
E8zga )
指针变量要和NULL进行比较,不要和布尔型和整形比较 j|TcmZGO
N}b/;Y
kB{
五、const和#define的比较 o8.KakrPP
S(eCG2gR
const有数据类型,#define没有数据类型 P7 O$*
)1wC].RFYm
个别编译器中const可以进行调试,#define不可以进行调试 4eK!1|1
F0W4B
在类中定义常量有两种方式 S:4'k^E
a,tzt
]>
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; lfp[(Ph)9
&[$qA
2、 用枚举代替const常量。 eRc+.m[
Qyvn A|&
C']TO/2q
六、C++函数中值的传递方式 z^$DXl@)h
|9T3" _MmJ
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) nfET;:{
KWbnSL8
void fun(char c) //pass by value ?pn<lW8d
D*BZp0x
void fun(char *str) //pass by pointer .|iMKRq
iZ
%KHqG
void fun(char &str) //pass by reference \B) a57
mIgc)"
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 +>h}Uz
B/.+&AJw
函数的类型不能省略,就算没有也要加个void *F0O*n*7W
g*?)o!_*
S7]\tw_L)
七、函数体中的指针或引用常量不能被返回 EITA[Ba B`
H6%QM}t
Char *func(void) b9Jah
]Ir{9EE
v
{ yH5^EY7rQ
5S`_q&
char str[]=”Hello Word”; XG FjqZr`
oU`8\n](
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 <"F\&M`G
? 3
{&"
return str; DKw%z8ft|
C4wJSQl_I
} )Be?axI
V}gP'f07zy
函数体内的指针变量并不会随着函数的消亡而自动释放 BK`NPC$a
@v{lH&K:;
TP7'tb
八、一个内存拷贝函数的实现体 q-kMqnQ
Syv[[Ek
void *memcpy(void *pvTo,const void *pvFrom,size_t size) Otq`4 5
QP/%+[E.
{ /orpQUHA
+c;/hM<IX.
assert((pvTo!=NULL)&&(pvFrom!=NULL)); ^*JpdmVhu
n${,r
byte *pbTo=(byte*)pvTo; //防止地址被改变 -5;Kyio
;^+#
byte *pbFrom=(byte*)pvFrom; 8>^(-ca_
${I$@qq83
while (size-- >0) ZslH2#
Axp#8
pbTo++ = pbForm++; b{Srd3
.x\fPjB
return pvTo; +6paM
-+MGs]),
} v`&
qZw4"&,j$
pkTg.70wU
九、内存的分配方式 GjTj..G/
Pf,S`Uw;
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 VGFWF3s
8/q6vk><
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 j7r! N^
$p_FrN{
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 [4qCW{x._
Xc)V;1
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 %f??O|O3
h M{&if
~{69&T}9
十、内存分配的注意事项 ttQX3rmF01
i>=d7'oR
用new或malloc分配内存时,必须要对此指针赋初值。 "p]F q,
+!_?f'kv`
用delete 或free释放内存后,必须要将指针指向NULL 0u0<)gdX
@L?X}'0xI4
不能修改指向常量的指针数据 X3nt*G1dL
Bfh[C]yy
F.;G6
十一、内容复制与比较 QG{).|pm
yWS#{|o(
//数组…… p1}Y|m!
'p0|wM_
char a[]=”Hello Word!”; 3Ee8_(E\
6AS'MD%&
char b[10]; ?l\1n,!:8
9iMQq40
strcpy(b,a); ?Q$LIoR
/48W]a}JS
if (strcmp(a,b)==0) 2 uuI_9 "^
>y
P`8Oq[
{} 2kv%k3Q{
.-kqt^Gc
//指针…… kk`BwRh)d;
, $;g'z!N
char a[]=”Hello Word!”; m]g"]U:
$^&SEz
char *p; q\ihye
!sF! (u7
p=new char[strlen(a)+1]; <9za!.(zu
OBF3)L]
strcpy(p,a); G'|Emu=4
w8~J5XS
if (strcmp(p,a)==0) m>po+7"b
y&y(<
{} fX.V+.rj
]>utLi5dX
ZqI.n4:9
十二、sizeof的问题 x.>E7
+
>{DHW1kF?
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 .3;bUJ1
@G/':N
char a[]=”Hello World!” $}[Tj0+:
P1PP#>E-2
char *p=a; &&1q@m,cP
[\9WqHs
count<<sizeof(a)<<end; //12字节 E\M{/.4 4
DNgQ.lV
count<<sizeof(p)<<endl; //4字节 m wuFXu/
)9,*s!)9
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 +B*8$^,V)
>$.u|a
void fun(char a[1000]) MSEBvZ-
wu*WA;FnA
{ =hV-E
D
V/j]UK0$
count<<sizeof(a)<<endl; //输出4而不是1000 a
S-
rng
dEXHd@"H
} Pn{yk`6E
T;- Zl[H
#unE>#DW
十三、关于指针 Y^)VHE]
&77]h%B>
1、 指针创建时必须被初始化 ivdw1g|)h
{Y5h*BD>
2、 指针在free 或delete后必须置为NULL v{rc5 ]\R
c$f|a$$b
3、 指针的长度都为4字节 ixJUq o
-_jV.`t
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 ;F&wGe
kO<`RHlX=
char *p=new char[100]; m RCgKW<
R|Ft@]
strcpy(p,”Hello World”); =#XsY,r
A!v-[AI[
delete []p; //注意前面的[]号 CiP-Zh[gZ
SwQ.tK1p
p=NULL; <!,q:[ee5
,8(%J3J
5、数组指针的内容不能超过数组指针的最大容易。 !DnG)4#
(.,E6H|zI
如: -
Pz
)O@ ;
ADX}
char *p=new char[5]; XA])<dZ
+DKrX
strcpy(p,”Hello World”); //报错 目标容易不够大 oWyg/{M
[BhpfZNKRA
delete []p; //注意前面的[]号 S&-sl
hoC}@8_
p=NULL; .Jdw:
e,E;\x
&
^a`zvrE
v
十四、关于malloc/free 和new /delete xsRMF&8L
/3%]Ggwe
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 /2u;w!oi.
ilK8V4k<T)
l 注意:malloc/free是库函数,new/delete是运算符 |PN-,f{ -
|xzqYu?o
l malloc/free不能执行构造函数与析构函数,而new/delete可以 Coq0Kzhsab
$2BRi@
l new/delete不能在C上运行,所以malloc/free不能被淘汰 EpGe'S
[[D}vL8d
l 两者都必须要成对使用 +2oZB]GPL
9[N'HpQ3
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 :kZ2N67
p!'wOThO`
z@y*
jT
十五、C++的特性 ]_BG"IR!..
"EpE!jh
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 17D167\X
}sy3Mrb
重载和内联:即可用于全局函数,也可用于类的成员函数; LWbWj ^
MC#bo{Bq3-
Const和Virtual:只可用于类的成员函数; |iM*}Ix-
?vRz}hiy
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 F__>`Dol
NtTLvO6
覆盖是指派生类函数覆盖基类函数 o\]e}+1[o
J=K3S9:n]g
函数名相同; z,rWj][P
Cw{#(xX
参数相同; %o4d43uZ
C`mXEX5
基类函数必须有Virtual关键字; Tf@t.4\
Q\=u2}/z0
不同的范围(派生类和基类)。 *MagicA
ZJ=C[s!wu
隐藏是指派生类屏蔽了基类的同名函数相同 EZP2Bb5g
0nie>
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 D3.sR\Hxf
dc&Qi_W
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 BpP\C!:^
!+)$;`
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 `*oLEXYN
n^Z?u9VR
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 ;8
McG83
!W$Br\<
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 62(WZX%b
|P?8<8p
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: wuYo@DDU#
q/OraPAB
将void Func(A a) 改为void Func(const A &a)。 cJ8*[H<NV
xC;$/u%'
而void func(int a)就没必要改成void func(const int &a); n;rOH[P
F$ h/k^
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 McsqMI6
qE,%$0g
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 q=nMZVVlF(
%oor7 -l
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; [/#n+sz.A
*fd` .}
oub4/0tN,~
十六、extern“C”有什么作用? LnJ7i"Q
<K\F/`c
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 [2\`Wh:%P
JAiV7v4&R
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 19#)#
n^
;,4J:zvZdQ
;%k%AXw
十七、构造函数与析构函数 |d`?wm-
9hguC yr@h
派生类的构造函数应在初始化表里调用基类的构造函数; l%w7N9
HdnSs0/
派生类和基类的析构函数应加Virtual关键字。 dJ&s/Z/>E
fglZjT
不要小看构造函数和析构函数,其实编起来还是不容易。 ', &MYm\
&YMVoyVD
#include <iostream.h> cEQa 6
^y6CV4T+
class Base a0LX<}
*xjIl<`pK
{ Bpp9I;)c
mn4;$1~e>H
public: PQ(%5c1e
w`v\/a_
virtual ~Base() { cout<< "~Base" << endl ; } QA 9vH'
e.kt]l
}; U D(#u3z
Qv=Z
class Derived : public Base pxC5a i
CFA>
{ bbM
!<&F
e/3hb)#;
public: `&6]P :_qp
puyL(ohem
virtual ~Derived() { cout<< "~Derived" << endl ; } S\rfR N
v;8XRR:
}; lpM{@JC
Smux&e
void main(void) fh3
6
$3Ia+O
{ m{yON&y
syfR5wc
Base * pB = new Derived; // upcast Bx)&MYY}[[
4%7*tVG
delete pB; -XyuA:pxx
H}~^,B2;
} .KSGma6]
?!66yn
输出结果为: `qgJE_GC
/W>"G1)
~Derived 7L6M#B[)e5
zVa+5\Q
~Base ZSSgc0u^?
?yb{DZ46
如果析构函数不为虚,那么输出结果为 D-!%L<<
zK92:+^C
~Base BkeP?X
m>!#}EJ|
el%Qxak`"
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 ;CZcY] ol
BYf"l8^,
仿止该头文件被重复引用