一、#include “filename.h”和#include <filename.h>的区别 As|e=ut(
FD8d-G
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 gS!zaD7Nr
QRdh2YH`
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 P\$%p-G
\
Ju7.3.
PSU}fo
二、头文件的作用 }4q1"iMlO
N3\vd_D(
加强安全检测 T=[/x=
nz/cs n
通过头文件可能方便地调用库功能,而不必关心其实现方式 nR,QqIFFw
g7v(g?
(J.U{N v
三、* , &修饰符的位置 Sj<]~*y"
b%xG^jUXsX
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 }u;`k'J@
GjX6noqT
cJ'OqV F
四、if语句 #?DoP]1Y
($,qxPOn
不要将布尔变量与任何值进行比较,那会很容易出错的。 whQJWi=ck
CS;4 ysNf
整形变量必须要有类型相同的值进行比较 5M#LO@U
n}8}:3"
浮点变量最好少比点,就算要比也要有值进行限制 Eo0/cln|
~6#O5plKc
指针变量要和NULL进行比较,不要和布尔型和整形比较 1-sG`%
T:*l+<?
j;EH[3
五、const和#define的比较 }(9ZME<(
a-NicjV#
const有数据类型,#define没有数据类型 V=H :`n3k
Bm+Ca:p%
个别编译器中const可以进行调试,#define不可以进行调试 ,Y7QmbX^
5jsZJpk$
在类中定义常量有两种方式 wB"`lY
C/q!!
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; 3 ]pHc)p!.
se29IhS!e
2、 用枚举代替const常量。 #l!nBY ~
[6\b(kS+
sL#MYW5E
六、C++函数中值的传递方式
,: qk+
vywpX^KPv
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) 9<5S!?JL
j7J'd?l
void fun(char c) //pass by value nPUD6<bF
U,Fyi6{~
void fun(char *str) //pass by pointer c6VyF=2q
*rA]q' jM
void fun(char &str) //pass by reference T _fM\jdI
\%&eDE 0
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 plM:7#eA
'i4L.&
函数的类型不能省略,就算没有也要加个void 7\yh<?`V8
tNz(s)
dd*p_4;
七、函数体中的指针或引用常量不能被返回 U|x#'jGo'
]D,\(|
Char *func(void) xL"O~jTS
T@a|*.V
{ M[(pLYq:
`yO'-(@"gY
char str[]=”Hello Word”; zpZfsn!
w^NQLV S
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 Gr#WD=I-}
I:("f+
H
return str; .AZwVP<
/O~Np|~v
} "<LWz&e^^
gyuBmY
函数体内的指针变量并不会随着函数的消亡而自动释放 /@I`V?Q!a
JX{_,2*$
/i#";~sO
八、一个内存拷贝函数的实现体 (p<pF].
M{4XNE]m
void *memcpy(void *pvTo,const void *pvFrom,size_t size) ?$l|];m)-
rR
8 6D
{ n]i#&[*A(
x,ZF+vE
assert((pvTo!=NULL)&&(pvFrom!=NULL)); <. *bJ
ILqBa:J
byte *pbTo=(byte*)pvTo; //防止地址被改变 m=SI *V
b`@J"E}
byte *pbFrom=(byte*)pvFrom; 7VL|\^Y `q
na"!"C
s3
while (size-- >0) dFyGI?
[bRE=Zr$Ry
pbTo++ = pbForm++; Kxg@( Q
J_?v=dW`
return pvTo; :Qhrh(i
b'Km-'MtH
} "p7nngn~
U_l9CZ
YoBe!-E
九、内存的分配方式 Gr#3GvL
u@CQ+pnf:(
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 gd*2*o$g(
T5z]=Pd"^
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 xF@&wg
jFUpf.v2
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 >H ?k0M`L
>##Z}auY
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 D:/q<<|
w)`XM
57-Hx;
十、内存分配的注意事项 *l=(?Pe<
Eku9u
用new或malloc分配内存时,必须要对此指针赋初值。 RB|i<`Z
8g
Z)c\
用delete 或free释放内存后,必须要将指针指向NULL @5ud{"|2
2`TV(U@
不能修改指向常量的指针数据 c+
e~BN
Ka_;~LS>(
Fk^N7EJ:$
十一、内容复制与比较 *UJ4\
}>d
//数组…… }}i'8
G]4Ca5;Z!N
char a[]=”Hello Word!”; *} ?
n,2
char b[10]; =^i K^)
mEsb_3?#+
strcpy(b,a); D:f=Z?L)>
Od)y4nr3~
if (strcmp(a,b)==0) gdA2u;q
.Z
67
{} y^ |u'XK
],k~t5+
//指针…… 7eAV2.
se`Eez}
char a[]=”Hello Word!”; ~> Q9
U3Z=X TB
char *p; (:HT|gKoE
=$fz</S=J
p=new char[strlen(a)+1]; &JcatI
-5 D<zP/
strcpy(p,a); %1.F;-GdsW
mO;QT
if (strcmp(p,a)==0) I<ohh`.
%^L{K[}
{} w.a9}GC
,(pp+hNq
3h d30o
十二、sizeof的问题 6#!CBY^{
$`55 E(
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 _p*8ke
*LU/3H|}
char a[]=”Hello World!” .<F46?HS
`SsoRPW&$
char *p=a; 7XK0vKmW3
8hD[z}
count<<sizeof(a)<<end; //12字节 Cj<8r S4+
tP7<WGHd/
count<<sizeof(p)<<endl; //4字节 S`U8\KTi
o3/o2[s
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 #-<Go'yF
4&sf{tI
void fun(char a[1000]) ,1#? 0q
LwK]fFtu
{ @$ Zh^+x!
Z17b=xJw
count<<sizeof(a)<<endl; //输出4而不是1000 BZ1wE1 t
Y~85Z0l
} gS5MoW1
_ERtL5^
G<n75!
十三、关于指针 M|mfkIk0MB
]}XDDPbZ}
1、 指针创建时必须被初始化 $Gv@lZ@=
>kK@tJn
2、 指针在free 或delete后必须置为NULL ZBK0`7#&EH
H3<tsK=:
3、 指针的长度都为4字节 z3K$gEve
5@m
,*n&[
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 ]690ey$E:j
(.cA'f?h
char *p=new char[100]; HS/.H,X
.Y;f9R
strcpy(p,”Hello World”); _ZK^JS
N*}soMPV^.
delete []p; //注意前面的[]号 N68$b#9Ry
k`8O/J
p=NULL; t4_yp_
?J2A1iuq3
5、数组指针的内容不能超过数组指针的最大容易。 <&l$xn
MmN{f~Kq9
如: #0aBQ+_8H
eTvWkpK+
char *p=new char[5]; ;+E]F8G9r
'7sf)0\:<p
strcpy(p,”Hello World”); //报错 目标容易不够大 PJC(:R(j
<-`.u`
delete []p; //注意前面的[]号 ,%*UF6B
M
BX0lk
p=NULL; $h{m")]
:^3 )[.m
KD &nLm!
十四、关于malloc/free 和new /delete cQ j`W
*
I"88O4\@
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 Hyy b0c^=
QIGU i,R
l 注意:malloc/free是库函数,new/delete是运算符 eyD V911
C6;2Dd]"N
l malloc/free不能执行构造函数与析构函数,而new/delete可以 [g/D<g5O
z_$c_J
l new/delete不能在C上运行,所以malloc/free不能被淘汰 g2|Myz)
i"0Bc{cQ
l 两者都必须要成对使用 5p[}<I{
hLLSmW(
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 djOjd,
3y}E*QE
d^aVP
十五、C++的特性 P[
:_"4U
OB(oOPH
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 x950,`zy
1RYrUg"s"
重载和内联:即可用于全局函数,也可用于类的成员函数; kWXLncE
Kd5'2"DI
Const和Virtual:只可用于类的成员函数; qg
oB}n%
z3+@[I$
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 .d1ff];
9;e!r DW,#
覆盖是指派生类函数覆盖基类函数 .C%
28fH
)y,^M3$?C
函数名相同; 5)!g.8-!
:snO*Zg
参数相同; $ZBYOA
yDafNH
基类函数必须有Virtual关键字; A9MM^jV8
<giBL L!
不同的范围(派生类和基类)。 10FiA;
|:1{B1sqA
隐藏是指派生类屏蔽了基类的同名函数相同 .xsfq*3e5
7y'uZAF
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 ^<CVQ8R7
`pfIgryns
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 H#SQ>vyAV
@(,1}3s
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 !{lH*
XDemdMy$
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 Z10Vx2B
k7CKl;Fck
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 ' P?h?w^T
faQmkO
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: !RI _Uph
|3'
将void Func(A a) 改为void Func(const A &a)。 7Z< ~{eD,
FDz`U:8
而void func(int a)就没必要改成void func(const int &a); HT;^u"a~
]3_b3@k
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 ,;`f* #
Tlw'05\{J
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 7Z6=e6/\
WoEK #,I;
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; nq M7Is
p~$cwbQ!
O(T5
十六、extern“C”有什么作用? $H)^o!
4@PA+(kvS
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 Xqf,_I=V
|THpkfW
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 :o'x?]
o!M8V ^vW
4Z)s8sD KW
十七、构造函数与析构函数 ~bLx2=-"
\R#SoOd
派生类的构造函数应在初始化表里调用基类的构造函数; )'djqpM.
%k!CjW3
派生类和基类的析构函数应加Virtual关键字。 = s&Rk~2b/
xa~]t<2
不要小看构造函数和析构函数,其实编起来还是不容易。 X94a
mJSfn"b}K
#include <iostream.h> c#n
2!
'FErk~}/4s
class Base %fj5;}E.
6cH8Jr _
{ T`&zQQ6F'
rW{!8FhI
public: C~ 1]
]@{Lx>Oh"
virtual ~Base() { cout<< "~Base" << endl ; } my?Ly(#
IVR%H_uz
}; >+2&7u
9kL,69d2
class Derived : public Base bv+u7B6,
k#].nQG
{ QZzamT)"
[l23b{
public: q(KjhM
0fsVbC
virtual ~Derived() { cout<< "~Derived" << endl ; } -vvyG
@-$8)?`q
}; #<*Vc6pC
AC,RS7
void main(void) -o ).<
=Hi@q
"
{ ^hIdmTf6
Z8|<%1Kge
Base * pB = new Derived; // upcast ]5ZXgz
,d#*i
delete pB; 6r)P&J
![_x/F9
} 'cD?0ou`o
idI w7hi4
输出结果为: a1Fx|#!
mq
kaBjA*
~Derived S_ATsG*(
}3(!kW
~Base V1aP_G-:
hOj{y2sc
如果析构函数不为虚,那么输出结果为 @62T:Vl
'}.Yf_
~Base /R#zu_i
">H*InF
{9x_E {
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 <Ky-3:pxeM
WZ CI*'
仿止该头文件被重复引用