一、#include “filename.h”和#include <filename.h>的区别 Esh3cn4
dm;H0v+Y'
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 h#a;(F4_7
~xI1@^r
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 v,z s
dr"d
$U=E7JO
U(#)[S,
二、头文件的作用 m>dZ n
?
tre)
加强安全检测 bH+x `]{A
i
oCoFj
通过头文件可能方便地调用库功能,而不必关心其实现方式 .Y B}w
{;.q?mj
E+ wd9/;
三、* , &修饰符的位置 90JD`Nz
g$C-G5/bjD
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 v^;-w~?3
=2&/Cn4
[KrWL;[1<
四、if语句 VA4>!t)
7w}D2|+
不要将布尔变量与任何值进行比较,那会很容易出错的。 3I!xa*u
l|#WQXs*c{
整形变量必须要有类型相同的值进行比较 m8KJ~02l#
jwsl"zL
浮点变量最好少比点,就算要比也要有值进行限制 1,cd[^`.
9=,^^,q
指针变量要和NULL进行比较,不要和布尔型和整形比较 @oC# k<
Ki#({~
7P3PQ%:
五、const和#define的比较 %7tQam
Z4YQ5O5
const有数据类型,#define没有数据类型 Q y(Gy'q~
+$]eA'Bh@
个别编译器中const可以进行调试,#define不可以进行调试 =+um:*a.
I5RV:e5b
在类中定义常量有两种方式 3L2@C%
R Wa4O#
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; en\shc{R]`
BR8W8nRb
2、 用枚举代替const常量。 nya-Io.
om 3$=
+r EqE/QF
六、C++函数中值的传递方式 u<8 f;C_
OkSJob
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) yX:A?U
e&&;"^@-
void fun(char c) //pass by value .<`W2*1
|12Cg>;j*n
void fun(char *str) //pass by pointer 0,)Ao8
XD\RD
void fun(char &str) //pass by reference h&|wqna
NwQexYm1_
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 H^jFvAI,8
+ -e8MvP
函数的类型不能省略,就算没有也要加个void tT7< V{i4
e@k`C{{C]o
<:#O*Y{
七、函数体中的指针或引用常量不能被返回 xl5n(~g)p
bS
'a )
Char *func(void) 3#>;h
ejj|l
{ jF}zv
4}{S8fGk%
char str[]=”Hello Word”; dZ!Wj7K)
x}TDb0V
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 1j*I`xZ
&fBLPF% 6
return str; QZufQRfr{
G~ZDXQ>5CP
} G9\Bi-'ul
rl)(4ad=
函数体内的指针变量并不会随着函数的消亡而自动释放 .%+`e
+Ux)m4}j
u>;#.N/
八、一个内存拷贝函数的实现体 oRM EC7!A0
2G"mm(
void *memcpy(void *pvTo,const void *pvFrom,size_t size) =YX/]g|9K
&J|3uY,'j
{ ok5
{c
Cna@3)_
assert((pvTo!=NULL)&&(pvFrom!=NULL)); 0pYz8OB
L K9vvQz
byte *pbTo=(byte*)pvTo; //防止地址被改变 <!:,(V>F(C
*BVkviqxz
byte *pbFrom=(byte*)pvFrom; cL*D_)?8
^SCZ
while (size-- >0) -tT{h4
cHK)e2r
pbTo++ = pbForm++; L>{E8qv>w
\()\pp~4
return pvTo; M;W{A)0i1
"}DuAs
} =mCUuY#
I/9ZUxQCyG
.LafP}%
九、内存的分配方式 P,!W\N%3
9>psQ0IRvr
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 P*/p x4;6
,
j,[4^
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 wd*i~A3+?
I"3Qdi
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 n6WSTh
3a#637%
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 V~5vVY_HG&
GZQ)TzR
Kv+E"2d
十、内存分配的注意事项 uf`o\wqU
$c0SWz
用new或malloc分配内存时,必须要对此指针赋初值。 >0+m
IGql^,b
用delete 或free释放内存后,必须要将指针指向NULL yVQqz
Q"VFcp:
不能修改指向常量的指针数据 x{ ~-YzWho
+n9&q#ah
AO;+XP=
十一、内容复制与比较 *ok89ad
({![
//数组…… -O~WHi5}
'.atbl
char a[]=”Hello Word!”; hr@KWE`
+Qu~UK\
char b[10]; 60~{sk~E
7r"!&P*,
strcpy(b,a); x:;8U i"&B
rf;R"Uc
if (strcmp(a,b)==0) nP'ab_>b
RNoS7[&
{} w[PW-m^`
}?*:uf
//指针…… B_`A[0H
-K}@Gp
char a[]=”Hello Word!”; nT|fDD|
,a$LT
char *p; kp<9o!?)
#k)G1Y[c
p=new char[strlen(a)+1]; 0plRsZ}
OD>-^W t;%
strcpy(p,a); I$qL=
{ +
[rJ_
if (strcmp(p,a)==0) `mw@"
28X)s!W'
{} ~DqNA%Mb
U <4<8'
6g akopZO
十二、sizeof的问题 R(pvUm&L
]}>GUXe)^
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 Fhxg^
$C#~c1w
char a[]=”Hello World!” s}|IRDpp
~ D3'-,n[
char *p=a; h]@Xucc
J_rCo4}
count<<sizeof(a)<<end; //12字节 Gjy'30IF
\FVR'A1
count<<sizeof(p)<<endl; //4字节
Q:_pW<^
1Lj\"+.
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 !S(jT?'w
&e,xN;
void fun(char a[1000]) q;kMeE*
1+#Vj#
{ Zpu>T2Tp
wQ.ild
count<<sizeof(a)<<endl; //输出4而不是1000 @gxO%@@
.V/TVz!b
} D\*raQ`n
D*D83z OzN
<YJU?G:@
十三、关于指针 /#>?wy<s~
db#y]>^l
1、 指针创建时必须被初始化 @ULr)&9
[FyE{NfiJ%
2、 指针在free 或delete后必须置为NULL =9pFb!KX
z)|56
F7'
3、 指针的长度都为4字节 uu#ALB
Jm
DeXnE$XH
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 IUu[`\b=
{'d?vm!r
char *p=new char[100]; !(SaE'
xZ,g6s2o
strcpy(p,”Hello World”); AFMAgf{bD
H.i_,ZF
delete []p; //注意前面的[]号 hrcR"OZ~X
[xI@)5Xk
p=NULL; &lGp
/m:
K bwWrf>
5、数组指针的内容不能超过数组指针的最大容易。 pOH_ CXw
^8V]g1]fiG
如: CH9#<?l
p(Qm\g<
char *p=new char[5]; /3+7a\|mKr
nHT2M{R
strcpy(p,”Hello World”); //报错 目标容易不够大 =euoSH
D}
YJ!6)d?C.
delete []p; //注意前面的[]号 >mt<`s
vZXyc*
p=NULL; IL>Gi`Y&
39m#
+Do7rl
十四、关于malloc/free 和new /delete 8Cm^#S,+
&p4q# p7,
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 urog.Q
:_H$*Q=1
l 注意:malloc/free是库函数,new/delete是运算符 Z,u:g c+*
rcQ?E=V2O
l malloc/free不能执行构造函数与析构函数,而new/delete可以 Sf*VkH
0c:CA>F
l new/delete不能在C上运行,所以malloc/free不能被淘汰 %C)U
F
?}lCS7&
l 两者都必须要成对使用 0V`/oaW;
1~5={eI
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 g<{~f
t0?BU~f
RHB>svT^K>
十五、C++的特性 C(?lp
i>e7 5`9
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 .GS|H d
R8HA X
重载和内联:即可用于全局函数,也可用于类的成员函数; Em
_miU
<pPI:D@G
Const和Virtual:只可用于类的成员函数; qtgj"4,:`
@rVmr{UE
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 ]A'e+RD4k
x{ZcF=4
覆盖是指派生类函数覆盖基类函数 0>.'w\,87B
7dU X(D,?
函数名相同; q .?D{[2
L!e@T'
参数相同; S liF$}J
N*o+m~:y
基类函数必须有Virtual关键字; ][0HJG{{g
I#9K/[
不同的范围(派生类和基类)。 Y
@K9Hl
} 10Dvt>+
隐藏是指派生类屏蔽了基类的同名函数相同 H[6d@m- Z
3btciR!N]
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 A
7TP1
i&?~QQP`
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 Y3-15:-
~[,E
i k
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 W;0_@!?mr}
$v>- @
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 9K%E+_7b
tc#
rL
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 &,K;F'
\w`Il"}V
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如:
G%4vZPA
az19-QIcg
将void Func(A a) 改为void Func(const A &a)。 E7j]"\~ i
ql_aDoj
而void func(int a)就没必要改成void func(const int &a); jPbL3"0A&
9]kWM]B)o
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 8BWLi5R[
QMkLAZ
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 Y.&z $+
O0~[]3Y[=
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; sy]1Ba%
lYq
R6^
iaPY>EP1
十六、extern“C”有什么作用? 1L^\TC
WlG/7$
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 3
vE;s"/
#<l;YT8
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 Ba@UX(t
b}k`'++2,
7(wY4T
十七、构造函数与析构函数 ^8We}bs-c
1k
"*@Z<
派生类的构造函数应在初始化表里调用基类的构造函数; h`jtmhoz
)%UO@4
派生类和基类的析构函数应加Virtual关键字。 od-N7lp#
QvqX3FU
不要小看构造函数和析构函数,其实编起来还是不容易。 <tFq6|
q
\0>SG
#include <iostream.h> Fet>KacTht
Q%KS$nP9
class Base m-ZVl j
Q2iu}~
{ P^.L0T5g
][#]4_
public: V=1Y&y
G$`/86A )
virtual ~Base() { cout<< "~Base" << endl ; } _%"/I96'
LD#]"k
}; Ue~M.LZb
E+[K?W5
class Derived : public Base /|hKZTZJdN
X@jml$;$
{ Z
wIsEJz
*`mwm:4
public: Fe`$mtPu .
zq(AN<
virtual ~Derived() { cout<< "~Derived" << endl ; } +dIg&}Tr
_[IN9ZC 2G
}; 9G 9!=J
Z>M0[DJ_
void main(void) NcFHvK
# l}Y1^PDd
{ i!sKL%z}
:Q!U;33aG
Base * pB = new Derived; // upcast ;R|5sCb/m
mWCY%o@
delete pB; E3sl"d;~
IQY\L@"
} A"i40 @+
JtvAi\52$
输出结果为: ZShRE"`
</Q<*@p?
~Derived ~#7=gI&p@
r1JKTuuo
~Base `epO/Uu\~u
l<! ?`V6}
如果析构函数不为虚,那么输出结果为 UC\CCDV#^
$x#Y\dpS
~Base &mp=j GR
b-yfBO
YN.rj-;^+
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 WEOW6UV(
9<G-uF
仿止该头文件被重复引用