一、#include “filename.h”和#include <filename.h>的区别 V`,[=u?c
qTHg[sME
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 l5';?>!s
E#$_uZ4
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 pq?[ wp"
rtL9cw5
f=_?<I{
二、头文件的作用 IHbo w0'
cm@ oun
加强安全检测 1LE^dS^V
*OOa)P{^D
通过头文件可能方便地调用库功能,而不必关心其实现方式 .8qzU47E
EO/cW<uV'
;D"P9b]9$
三、* , &修饰符的位置 s$>m0^
"gN* J)!x
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 p
(xD/E
4zqE?$HM'
\kV7NA
四、if语句 _RaVnMJKX4
"aWX:WL&}s
不要将布尔变量与任何值进行比较,那会很容易出错的。 qa$[L@h>
nUud?F^_
整形变量必须要有类型相同的值进行比较 jaO#><f
_c9
WWp?
浮点变量最好少比点,就算要比也要有值进行限制 !qXq
y}?w
GQ-e$D@SfB
指针变量要和NULL进行比较,不要和布尔型和整形比较 0|s$vqc
j+13H+dN
c+b:K
五、const和#define的比较 DA MpR3
/ik)4]>
const有数据类型,#define没有数据类型 jO&f*rxN
9SH<d)^
个别编译器中const可以进行调试,#define不可以进行调试 Gp ^ owr
TtwJ,&b
在类中定义常量有两种方式 0^!,[oh6*
i. u15$
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; R!/,E
@0UwI%.
2、 用枚举代替const常量。 SEQO2`]e:
XuFm4DEJ
?mYV\kDt\
六、C++函数中值的传递方式 1!;"bHpk
7:VEM;[d
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) ##`;Eh0a
`FYtiv?G
void fun(char c) //pass by value Ng."+&
XU;{28P
void fun(char *str) //pass by pointer 4lY&=_K[)
@}&,W
N%
void fun(char &str) //pass by reference uD ?I>7
p9&gEW
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 ^b"x|8
OP|.I._I
函数的类型不能省略,就算没有也要加个void xyS2_Q
o]|oAN9
lrmt)BLoh
七、函数体中的指针或引用常量不能被返回 f>s#Ngvc
2w x[D
Char *func(void) ~b>nCP8q
%qNj{<&
{ 5&n988gC8
NWQPOq#
char str[]=”Hello Word”; p-T~x$"c|
2[8fFo>
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 de=5=>P7
Sr ztTfY
return str; g/U$!d_
9{9#AI.G
} }j5R@I6P
[.#p
函数体内的指针变量并不会随着函数的消亡而自动释放 f
gK2.;>
bG5^h
T.R>xd`9
"
八、一个内存拷贝函数的实现体 taWirqd9
d739UhKC
void *memcpy(void *pvTo,const void *pvFrom,size_t size) rSF;Lp)}
m0%iw1OsH%
{ r{R[[]p
w!B,kqTG
assert((pvTo!=NULL)&&(pvFrom!=NULL)); r21?c|IP
M73VeV3DL
byte *pbTo=(byte*)pvTo; //防止地址被改变 D% v:PYf
FhY{;-W(T
byte *pbFrom=(byte*)pvFrom; ]Efh(Gb]
%2@ Tj}xa
while (size-- >0) |z!q
r}i
S|{Yvyp
pbTo++ = pbForm++; {UX"Epd);n
KD,^*FkkL
return pvTo; AMh37Xo
r%Q8)nEo
} .\ ;l-U
f7_\).T
="5k\1W1M
九、内存的分配方式 r/N[7*i
|aI|yq)
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 IL+#ynC
4DQ07w
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 +X* F<6mZ
' D)1ka.
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 K)Df}fVOc
CU#L *kz
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 27Kc-rcB
|MOn0*
Xmf
十、内存分配的注意事项 $n=W2WJ6f
<O,'5+zG%
用new或malloc分配内存时,必须要对此指针赋初值。 ++Rdv0~
3JlC/v#0
用delete 或free释放内存后,必须要将指针指向NULL T =eT^?v
k8InbX[
不能修改指向常量的指针数据 2|0Je^$|
Eonq'Re$
%K&+~CJE
十一、内容复制与比较 G?Qe"4
.
L?3VyBE
//数组…… l]a^"4L4`o
V9 +xL 1U#
char a[]=”Hello Word!”; =Q/w% 8G
CbTf"pl
char b[10]; Qag|nLoT
,GdxUld
strcpy(b,a); 6T^N!3p_
oJlN.Q#u&
if (strcmp(a,b)==0) m+D2hK*
.;<7424(%
{} pX>ua5Z
7%:??*"~
//指针…… q=P
f^Xp
652u Z};e
char a[]=”Hello Word!”; [5]R?bQ0q{
4&FNU)tt
char *p; S_(&UeTC
]yyU)V0Iu
p=new char[strlen(a)+1]; g)=V#Bglv
$Qn&jI38
strcpy(p,a); +L`V[;
kbfuvJ>
if (strcmp(p,a)==0) q
Axf5
L]c 8d
{} uHfhRc9
lSZ"y
Q+
+
$k07mb\
十二、sizeof的问题 4u3 \xR?w6
2^zg0!z
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 7^kH8qJ)
z{Hz;m:*_
char a[]=”Hello World!” $?H]S]#|}.
M?E9N{t8)a
char *p=a; H/cs_i
Y;fuh[#
count<<sizeof(a)<<end; //12字节 #[no~&E
DWF
>b
count<<sizeof(p)<<endl; //4字节 )v${&H
&tlR~?$e*
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 ,DE(5iDS
fswZM\@
void fun(char a[1000]) Eem 2qKj
Ix( 6
{ D"`%|`O
{@Blj3 ;w}
count<<sizeof(a)<<endl; //输出4而不是1000 X }m7@r@
1t0bUf;(M
} i{<8
hLO
! a86iHU
ot-(4Y
十三、关于指针 Ly^E& ,)
X32RZ9y
1、 指针创建时必须被初始化 5\uNEs$T
@)
2、 指针在free 或delete后必须置为NULL L=d$"Q
qv.[k<~a>
3、 指针的长度都为4字节 IJ hxE
y' 2<qj
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 cge-'/8w%
$`^H:Djr
char *p=new char[100]; Zn?8\
}phz7N9
strcpy(p,”Hello World”); OZ eiHX!
8r2XGR
delete []p; //注意前面的[]号 ,yTN$K%M
{;U} :Dx
p=NULL; w+Ad$4Pf"
D*|(
p6v1&
5、数组指针的内容不能超过数组指针的最大容易。 -s{R/ 6:
[Dnusp7e
如: (&q@~
dJ
aLV~|$:2
char *p=new char[5]; [fd~nD#.
%rFP#L
strcpy(p,”Hello World”); //报错 目标容易不够大 D[V`^CTu
H(MB5
delete []p; //注意前面的[]号 #X4LLS]VV
!$xzAX,
p=NULL; LOe4c0C6Ca
#1MKEfv(~
55LgBD
十四、关于malloc/free 和new /delete P~&O4['<
TLy;4R2Nn
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 &q.)2o#Q.
"K8nxnq
l 注意:malloc/free是库函数,new/delete是运算符 3 Q@9S
n1_ %Td
l malloc/free不能执行构造函数与析构函数,而new/delete可以 wyp{KIV
STv(kQs
l new/delete不能在C上运行,所以malloc/free不能被淘汰 \{kHSV%z
pH^ z
l 两者都必须要成对使用 b7Yq_%+
cS4xe(n8
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 aWdUuid
nZe\5`
AmZuo_
十五、C++的特性 I`lDWL
[S%J*sz~
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 HP#ki !'
9 _eS`,'
重载和内联:即可用于全局函数,也可用于类的成员函数; fH&zR#T7U4
'wa g |-
Const和Virtual:只可用于类的成员函数; ubD#I{~J
%@>YNPD`E
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 #sL/y
0xv\D0
覆盖是指派生类函数覆盖基类函数 Tu==49
k@7kNMl
函数名相同; @ozm;
O(odNQy~
参数相同; : sFo
c$/<l5Uw
基类函数必须有Virtual关键字; {JTmP `&l
CDJ$hu
不同的范围(派生类和基类)。 Il|GCj*N
{Wh BoD
隐藏是指派生类屏蔽了基类的同名函数相同 (Bsw/wv
STw oYn
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 y`({ .L
}N@n{bu+
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 f KHse$?_
3=IG#6)~C
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 $%B5$+
,eDu$8J9
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 <H!O:Mf_p
~bWhth2*
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 |"_ )zQ
)t5;d
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: >n(F4C-pl
TFYw
将void Func(A a) 改为void Func(const A &a)。 KLW&bJ$|j
S3QaYq"v
而void func(int a)就没必要改成void func(const int &a); R#D#{cC(
Y!F!@`%G
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 'bl%Y).9w
hc"6u\>
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 <M=';h^w2
GZ
<nXU>
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; W|0My0y
sSNCosb
f*v1J<1#
十六、extern“C”有什么作用? {|Bd?U;
2HSb.&7-G
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 l`* ( f9Q
4Q$!c{Y
r
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 h+5@I%WX
6oYIQ'hc
pG~'shD~Dn
十七、构造函数与析构函数 .ByU
@\!ww/QT
派生类的构造函数应在初始化表里调用基类的构造函数; (xbIUz.
kwOeHdV^
派生类和基类的析构函数应加Virtual关键字。 y^SyhG,V[
;c$@@l
不要小看构造函数和析构函数,其实编起来还是不容易。 7r['
1EQvcw#
#include <iostream.h> V+.Q0$~F5
\<=IMa0
class Base &lU Ny
L
xuF5/(__
{ g[AA,@p+
] ;&"1A
public: W\%q}q2?
4
]sCr+
virtual ~Base() { cout<< "~Base" << endl ; } Tn /Ut}]O
svqvG7
}; YQ+^
-(
(Z@T1k
class Derived : public Base O<>#>[
vkuc8 li
{ m!0N"AjA
VE*j*U
j
public: _!%M%
V!W1fb7V
virtual ~Derived() { cout<< "~Derived" << endl ; } (2d3jQN`
Hxn<(gd
G
}; yZ5x88 >
W~<m[#:6C
void main(void) R2CQXhiJ
qrpb[)Ll
{ f0u56I9
4
A5t*e
Base * pB = new Derived; // upcast BW>5?0E[4(
SD^E7W$?
delete pB; 5y040
N-
z,avQR&
} /,LfA2^_j{
o(zTNk5d
输出结果为: `Klrr
ODek%0=
~Derived x^X$M$o,l
mbGcDG[HQ
~Base *Wso3 6an
e6 2y
如果析构函数不为虚,那么输出结果为 )@_ugW-j
+2Z#M
~Base YNk|+A.<d
Ch7Egzl7?
i%MA"I\9
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 ` zY!`G
/'\;8A$J`
仿止该头文件被重复引用