一、#include “filename.h”和#include <filename.h>的区别 )l}Gwd]h
Yj+p^@{S2P
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 5[Sa7Mk
Ew>E]Ys
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 \{W}
};5d>#NK,Y
v8Ga@*
二、头文件的作用 LadE4:oy
APydZ
加强安全检测 &)4#0L4
pSM\(kVKa
通过头文件可能方便地调用库功能,而不必关心其实现方式 5>{S^i~!
.W[ 9G\
4[=vt
三、* , &修饰符的位置 '1|FqQ\.
d~NvS-u7
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 V^9c:!aI
F Xbf7G)H
O,m0Xb2s]~
四、if语句 nksx|i l
1D3{\v
不要将布尔变量与任何值进行比较,那会很容易出错的。 9?8Yf(MC%u
u-yVc*<,
整形变量必须要有类型相同的值进行比较 >K<n~;ON|
~4e4Gyx c
浮点变量最好少比点,就算要比也要有值进行限制 Uy$1X
`;?`XC"m
指针变量要和NULL进行比较,不要和布尔型和整形比较 >)E{Hs
s];jroW@u
H{Fww4pn
五、const和#define的比较 >NL4&MV:
;JQ:S~K9
const有数据类型,#define没有数据类型 S6~&g|T,
6x?3%0Km
个别编译器中const可以进行调试,#define不可以进行调试 z"[}Sk
{<f |h)r
在类中定义常量有两种方式 $CT2E
a!iG;:K
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; ;;r}=0V*=
Pe-1o#7~W
2、 用枚举代替const常量。 Jat|n97$
hq.XO=0" k
t|/{oAj
六、C++函数中值的传递方式 >M `ryM2=D
X:3W9`s)*
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) H_ecb;|mP
l)1FCDV
void fun(char c) //pass by value (P=q&]l[
'
];|
void fun(char *str) //pass by pointer j,:vK
{:peArO
void fun(char &str) //pass by reference $G
$147z
%yr(i 6L
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 TOH!vQP
h 3.6<vM
函数的类型不能省略,就算没有也要加个void PG@Uygahu
Y*}xD;c
k
KG8:F].u(
七、函数体中的指针或引用常量不能被返回 ONc-jU^
M.*3qWM
Char *func(void) -Y?C1DbKz
-chk\75
{ 3Gr:.V9=
*=b#>//
char str[]=”Hello Word”; zG"*B_l}+
Qj:`[#3?2
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 5Xe1a'n5]
.|Ee,Un
return str; hoJ{C 0
vv 7T/C
} dE ,NG)MH
/E%r@Rui3$
函数体内的指针变量并不会随着函数的消亡而自动释放 $N@EH;{_0
0P?\eoB@8
;XUiV$
八、一个内存拷贝函数的实现体 R=/^5DZ}
]&oQ6
void *memcpy(void *pvTo,const void *pvFrom,size_t size) ` D9sEt_/
,.Sd)JB'
{ :\Pk>a
8D)I~0\
assert((pvTo!=NULL)&&(pvFrom!=NULL)); 6 2YT)/i3
=W*Js %4
byte *pbTo=(byte*)pvTo; //防止地址被改变 }\-"L/D?+
w%Bo7 'o)V
byte *pbFrom=(byte*)pvFrom; 8dBG ZwyET
+f+#W
while (size-- >0) <"}Gvi
Iz^lED
pbTo++ = pbForm++; |^&j'k+A
qhIO7h
return pvTo; 2A,iY}R
U"0Ts!CABA
} BS(XEmJn&j
@ xBw'
0QakFt
九、内存的分配方式 =xf7lN'
"i5Rh^
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 fc,^H&
VK~ OL
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 <D1>;C
O]/BNacS
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 rB<za I\V
N.l\2S}
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 5VLJ:I?0O
u` j9m@`
8B|qNf `Yi
十、内存分配的注意事项 @An "ClDa
O=A(x m#
用new或malloc分配内存时,必须要对此指针赋初值。 %XUV[L}
b+6%Mu}o
用delete 或free释放内存后,必须要将指针指向NULL `H#G/zOr
~8htg8CZ`
不能修改指向常量的指针数据 /-mo8]J#2~
P p]Ygt'u
c}l?x
\/
十一、内容复制与比较 Z(gW(O9h.V
s .xJ},E9
//数组…… Qgel^"t]i
X-mhz3Q&a
char a[]=”Hello Word!”; 3WTNWz#h
{,Py%.vvR
char b[10]; |Nfi y
BY&+fKae
strcpy(b,a); xGU~FU
iuxS=3lT"K
if (strcmp(a,b)==0) r^jiK\*
A=+
|&+? t
{} ryKc7<
;`(l)X+7
//指针…… 'T_Vm%\)
Zd Li<1P*d
char a[]=”Hello Word!”; 1638U1
HpQuro'Qh
char *p; tsqkV7?
chQCl3&e^
p=new char[strlen(a)+1]; FVw4BUOmi
:v(fgS2\
strcpy(p,a); =Ll:Ba Q
SZ*Nr=X
if (strcmp(p,a)==0) u]!ZW&
F^xhhz&e
{} ;<?mMi@<E
)j^~=Sio.
~$@~X*K~
十二、sizeof的问题 <)J83D0$E
b-Q%cxJ
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 /xu#ZZ?8F_
1X7tN2tQ
char a[]=”Hello World!” -*QxZiKD
o;#9$j7QP!
char *p=a; g`690
Y#A0ud,
count<<sizeof(a)<<end; //12字节 P*\h)F/3}t
H`XE5Hk)P%
count<<sizeof(p)<<endl; //4字节
^kElb;d
YgFmJ.1
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 Go8?8*
IeZgF>
void fun(char a[1000])
FK2* O
%xH2jf
{ =HGC<#
js~?y|e8k
count<<sizeof(a)<<endl; //输出4而不是1000 7H~J?_
ap7ZT7KW
} a'U}.w}
,$xV&w8f\"
)T_o!/\*|*
十三、关于指针 Jh)x_&R&Q
e=yQFzQT)
1、 指针创建时必须被初始化 ?f{--|V
&/}reE*
2、 指针在free 或delete后必须置为NULL p}r1@L s
R}S@u@mOE
3、 指针的长度都为4字节 MzWVsV
lebwGW,!
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 !i`HjV0wS
x)h|!T=B~
char *p=new char[100]; :zWI"
>&mNC\PA
strcpy(p,”Hello World”); $}* bZ~
Hfw*\=p
delete []p; //注意前面的[]号 ?mRGFS
J2ryYdo>
p=NULL; ROv(O;.Ty
+li<y`aw0
5、数组指针的内容不能超过数组指针的最大容易。 vs`"BQYf
t\/i9CBn
如: f2abee
{&bjjM
char *p=new char[5]; V2&O]bR
zK5/0zMZ
strcpy(p,”Hello World”); //报错 目标容易不够大 ZYi."^l
+;ILj<!Z7
delete []p; //注意前面的[]号 C1V@\mRi
_(R1En1
p=NULL; p#yq 'kY
L93PDp4v
"Q>gQKgL
十四、关于malloc/free 和new /delete LxcC5/@\~(
VD,p<u{r
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 PGE|){
<
#2XX [d%
l 注意:malloc/free是库函数,new/delete是运算符 _~=qByD
.o._`"V
l malloc/free不能执行构造函数与析构函数,而new/delete可以 h
!yu. v
lhN2xg5x
l new/delete不能在C上运行,所以malloc/free不能被淘汰 {Y\W&Edw%
H2p lT
l 两者都必须要成对使用 nNN~Z'bG
$P{|^ou3a#
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 7jZE(|G-
5vfzSJ
!sJ*0
十五、C++的特性 ) Ekd
!P_8D*^9
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 h.~:UR*
sghQ!ux
重载和内联:即可用于全局函数,也可用于类的成员函数; 3\ !DsPgW
C'_^DPzj
Const和Virtual:只可用于类的成员函数; V\!6K
323zR*\m
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 cg]\R1Gm
d&@>P&AT
覆盖是指派生类函数覆盖基类函数 lVw77bZ
n B5 :X
函数名相同; b%TS37`^[
YM:;mX5B
参数相同; MHm=X8eg
x$6`k
基类函数必须有Virtual关键字; ~$bkWb*RJ
0# )I:5
不同的范围(派生类和基类)。 r}9a31i
/CE]7m,7~K
隐藏是指派生类屏蔽了基类的同名函数相同 vq.~8c1
Hju7gP=y}
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 lU}y%J@
QO-R>
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 >R9_;
Zs(I]^w;d
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 g}vOp3^
`2B,+ytW8
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 QXQ'QEG
e1EFZ,EcaO
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 kPt] [1jo
6c?;-5.
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: U:a-Wi+
5*q!:$
W
将void Func(A a) 改为void Func(const A &a)。 _>6xUt
,D6hJ_:
而void func(int a)就没必要改成void func(const int &a); Ez= Q{g
e13{G@
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 Zgw;AY.R>
7eM:YqT/#
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 s y ]k
u(Y! _
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; 0L
^WTq
-$@$
pZYcCc>6&
十六、extern“C”有什么作用? &sbKN[x M
(eG9b pqr
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 t7t?xk!2
~)ZMGx
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 8Moe8X#3
iEA$`LhO\A
)YKnFSm
十七、构造函数与析构函数 Xf4
#dvH0LX?
派生类的构造函数应在初始化表里调用基类的构造函数; o|tq&&! <
qHGwD20 ~
派生类和基类的析构函数应加Virtual关键字。 eplz5%<
'V*ixK8R0
不要小看构造函数和析构函数,其实编起来还是不容易。 :|Ckr-k"1e
xD:t$~
#include <iostream.h> TjUg8k
M_:_(y>l
class Base 3y[uH'
x344}\
{ zKY 9'y
h.QsI`@f
public: 3N5un`K7
y4V~fg;
virtual ~Base() { cout<< "~Base" << endl ; } ke+3J\;>
(9"w{pnlLc
}; J'Z!`R|
MHuQGc"e+4
class Derived : public Base Xscm>.di
9*thqs3J#d
{ g!#M0
4*)a3jI?
public: ^B>BA
4TPAD)C
virtual ~Derived() { cout<< "~Derived" << endl ; } d){o#@
lj U|9|v
}; w ,6zbI/
WN5`zD$
void main(void) b3h3$kIYN
p4Wy2.&Q
{ 8)NQt$lWp
"
hD6Z
Base * pB = new Derived; // upcast EJ%Kr$51K
\V1geSoE
delete pB; w_>SxSS7
65 P*Gu?
} $jc&Tk#
A ;06Zrf1
输出结果为: ^57G]$Q
J&B>"s,
~Derived ]]EOCGZ"
bzl-|+!yB
~Base Wubvvm8U
\\Z{[{OZ
如果析构函数不为虚,那么输出结果为 h@^d
Vg
e
hgUp =
~Base eB]R<a60
%6%QE'D
MnQ4,+ji-
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 MYmH?A
@_ZE_n
仿止该头文件被重复引用