一、#include “filename.h”和#include <filename.h>的区别 oFC)
NAFsFngqH
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 &tI#T)SSs
k|E]YvnfG
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 0ZI(/r
!~iGu\y
7C,T&g
1:
二、头文件的作用 IB5BO7J
-X1X)0v$
加强安全检测 n!ok?=(kQ
!K0JV|-?t
通过头文件可能方便地调用库功能,而不必关心其实现方式 F[`ZqW
mY&ud>,U:
u<tk G B
三、* , &修饰符的位置 ; y.E!
\gO,hST
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 Iw=Sq8
}nx=e#[g%2
T1Ta?b
四、if语句
*~VxC{
40P) 4w
不要将布尔变量与任何值进行比较,那会很容易出错的。 4FMF|U
c6AWn>H
整形变量必须要有类型相同的值进行比较 ]$iN#d|ZU
Tupiq
浮点变量最好少比点,就算要比也要有值进行限制 (Xxn\*S
n&XGBwgW
指针变量要和NULL进行比较,不要和布尔型和整形比较 {1lO
0t.p1
${&5]!E[>D
五、const和#define的比较 m:CTPzAt
`$5UHa2/
const有数据类型,#define没有数据类型 \ FzM4-
<G3&z#]#4
个别编译器中const可以进行调试,#define不可以进行调试 uOi&G:=
~P f5ORoe
在类中定义常量有两种方式 r.3KPiYK
g@v
s*xE
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; fP-|+TyO
A}VYb:u/
2、 用枚举代替const常量。 8HErE<_(
Oe]&(
I4_d[O9
六、C++函数中值的传递方式 lX!`zy{3k
i^"+5Eq[D
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) U9d:@9Y
=[tSd)D,y
void fun(char c) //pass by value 2 h|e
(M-ZQ
-
void fun(char *str) //pass by pointer H#d:kil Ny
i8pU|VpA
void fun(char &str) //pass by reference }=}>9DSM
b\55,La
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 %Kb9tHg
L\aBc}
函数的类型不能省略,就算没有也要加个void \x\
5D^Vc
MBr:?PE7
d+L#t
七、函数体中的指针或引用常量不能被返回 (jWss V1
Cpl;vQ
Char *func(void) wzWbB2Mb5
j) vlM+
{ R4's7k
4rNL":"O
char str[]=”Hello Word”; 1&)_(|p[C
||B;o-
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 A2H4k|8
l5t2\Fl
return str; Ss?CfRM
T=Z.U$
} M^madx6`
_GtBP'iN
函数体内的指针变量并不会随着函数的消亡而自动释放 U yqXMbw@
B5am1y{P#
8nNsrat
八、一个内存拷贝函数的实现体 C'mL&
Hgc=M
void *memcpy(void *pvTo,const void *pvFrom,size_t size) Oxx^[ju~
Uu p(6`7
{ F
phDF
}E^S]hdvz
assert((pvTo!=NULL)&&(pvFrom!=NULL)); X=X\F@V:u
B0UJq./`
byte *pbTo=(byte*)pvTo; //防止地址被改变 ZXb0Y2AVx
76fIC
byte *pbFrom=(byte*)pvFrom; L#h:*U{@40
JcO08n
while (size-- >0) B/uniR^x
T5lQIr@a
pbTo++ = pbForm++; &lc8G
Z+:D)L
return pvTo; [Gr*,nVvB
kMxazx1
} tJI,r_
_O:WG&a6
F1azZ(
九、内存的分配方式 o@E/r.uK
-7-['fX
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 SpTdj^ ]4>
p#d+>7
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 kUHE\L.Y]
/FY2vDfU6
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 =d;Vk
Yn51U6_S
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 {==pZpyyh
!UBO_X%dz
V1=*z
十、内存分配的注意事项 dx_6X!=.J
Bo_ym36N
用new或malloc分配内存时,必须要对此指针赋初值。 ZDLMMXx>
Bd0eC#UGkQ
用delete 或free释放内存后,必须要将指针指向NULL D #2yIec
o,Z{ w"
不能修改指向常量的指针数据 *iXe^ <6v
Bn wzcl
%Q|eiXD
十一、内容复制与比较 n(Y%Vmy
rx~[Zs+*
//数组…… .5HQ
<!^
[~`
char a[]=”Hello Word!”; !%L,*'
&Y>zT9]$K
char b[10]; 9|r* pK[
,%"xH4d
strcpy(b,a); h+UnZfm
5rxA<Gs
if (strcmp(a,b)==0) *6ZCDm&N
@ CsV]97`
{} SqPtWEq@P
Sq]pQ8
//指针…… Dma.r
`\$8`Zb;
char a[]=”Hello Word!”; A/*%J74v
%"3 )TN4
char *p; ~fN%WZ;_
UV7%4xM5v
p=new char[strlen(a)+1]; PK6iY7Qp)
#} ,x @]p
strcpy(p,a); ~XM[>M\qB
nn~YK
if (strcmp(p,a)==0) B;zt#H4
TvhJVVQ+?
{} N0TeqOi4Y
Iq5pAHm>M6
b}z`BRCc
十二、sizeof的问题 .#6MQJ]OH
RNJFSD.
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 Va<HU:<
'%iPVHK7
char a[]=”Hello World!” )6oGF>o>
5a`%)K
char *p=a; {5Lj8N5
6.Ie\5-a;
count<<sizeof(a)<<end; //12字节 @M;(K<%h
[uuj?Rbd
count<<sizeof(p)<<endl; //4字节 $< %B#axL
|WqOk~)[Z3
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 7v~j=Z>
'VnwG
void fun(char a[1000]) c=p=-j=.J
X~U >LLr
{ `x8Bn"
xp \S2@<
count<<sizeof(a)<<endl; //输出4而不是1000 u</8w&!
I+?hG6NM
} t1]6(@mj5
qk{'!Ii
<lwuTow
十三、关于指针 eQN.sl5
AHh#Fx+K
1、 指针创建时必须被初始化 a' FN 3
}<m{~32M
2、 指针在free 或delete后必须置为NULL |hzT;
,{}#8r` +*
3、 指针的长度都为4字节 !XE aF]8
&_-](w`
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 Mhpdaos
$g8}^1
char *p=new char[100]; y.a]r7
t%0?N<9YkU
strcpy(p,”Hello World”); :R6Q=g=
fv'4f$U
delete []p; //注意前面的[]号 85Y|CN] vQ
ROAI9sW0
p=NULL; 4*H"Z(HP
>%%=0!,yX
5、数组指针的内容不能超过数组指针的最大容易。 -$k>F#
[I+9dSM1t
如: cnNOZ$)
v"lf-c
char *p=new char[5]; 4iX-( ir,
+++pI.>(*Q
strcpy(p,”Hello World”); //报错 目标容易不够大 b{[*N
U@lV
delete []p; //注意前面的[]号 02b6s&L
QTJu7^O9
p=NULL; *o?i:LE]
D_D,t8_Y
e<+<lj"
十四、关于malloc/free 和new /delete mV\$q@sII
e-6w8*!i
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 #6> 6S;Ib
CY"i-e"q<Q
l 注意:malloc/free是库函数,new/delete是运算符 /'&;Q7!)
e1(h</M U2
l malloc/free不能执行构造函数与析构函数,而new/delete可以 c[(Pg%
n~r 9!m$<
l new/delete不能在C上运行,所以malloc/free不能被淘汰 RI.2F*|
';YgG<u
l 两者都必须要成对使用 D'i6",Z>
'CV^M(o'9
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 $[CA&Y.
;)/@Xx
J\`^:tcG
十五、C++的特性 mUXk9X%n
sg?@qc=g
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制
ZXXiL#^
#uvJH8)D
重载和内联:即可用于全局函数,也可用于类的成员函数; =4NqjSH
;bjnL>eW
Const和Virtual:只可用于类的成员函数; HYClm|
/=T"=bP#/
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 szq+@2:
4<gJ2a3
覆盖是指派生类函数覆盖基类函数 3oBC
(F5ttQPh
函数名相同; 78Y@OL_$
h8v>zNf'
参数相同; vOT*iax0
X0i3 _RVa
基类函数必须有Virtual关键字; "sbBe73 m
Lo`F
不同的范围(派生类和基类)。 /tKGwX]y
vA>W9OI
隐藏是指派生类屏蔽了基类的同名函数相同 ,b.n{91[]x
^#SBpLw
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 zy)i1d
_wu*M
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 r_o<SH
f_<Y\
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 |rPAC![=
!#}>Hv^N
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 ;93KG4a
6Z c)0I'
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 lo:~aJ8
"'{OIP
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: Bymny>.M
WYO\'W
将void Func(A a) 改为void Func(const A &a)。 Y3oMh,
i?>Hr|
而void func(int a)就没必要改成void func(const int &a); *\q8BZ
MUwVG>b8J~
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 AzjMv6N
h}6_ybmZ
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 tgN92Q.i6T
#5{sglC"|F
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; Z3;=w%W
Y mDn+VIg
h6QWH
十六、extern“C”有什么作用? Vyt
E
|5ONFde"0
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 FdxsUDL
&o.iUk
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 otq,R6 ^
l9Pu&M?5
In(NF#
十七、构造函数与析构函数 Mq+<mX7
~3 @*7B5Q
派生类的构造函数应在初始化表里调用基类的构造函数; Czu1 )y
*8-p7,D
派生类和基类的析构函数应加Virtual关键字。 otnV-7)@
a<p
%hY3
不要小看构造函数和析构函数,其实编起来还是不容易。 +Jq`$+%C
q$ >_WF#||
#include <iostream.h> 1n3$V:00
~e^)q>Lb7(
class Base <%?uYCD
Bbs 0v6&,
{ !R{em4 8D
r$DZkMue
public: aL)$b
x5vzPh`
virtual ~Base() { cout<< "~Base" << endl ; } j+0.=#{??
ZKQo#!}
}; yBe(^ n
ZR
mPP
class Derived : public Base `.8-cz
5"2@NL
{ ,.7vBt6 p
!E0fGh
public: =ZMF ]|
)52#:27F
virtual ~Derived() { cout<< "~Derived" << endl ; } jkCHi@
*1,=qRjL
}; BHclUwj
RAOKZ~`
void main(void) lk o3]A3
6o(lObfo
{ o16~l]Z|f
Hdna{@~
Base * pB = new Derived; // upcast Nh:4ys!P
U,HS;wo;t
delete pB; 6vWii)O.D
s((b"{fFb
} ">,K1:(D
!7Uu]m69n
输出结果为: kaC+I"4c
B[7A
~Derived `axQd%:AC
`D"1
gD}{A
~Base ir+8:./6
"i(U
如果析构函数不为虚,那么输出结果为 w(#:PsMo<
GZ,j?@
~Base )u
Qvt-
v?{vg?vI
2;}xN! 8
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 2{gwY85:
x{j+}'9
仿止该头文件被重复引用