一、#include “filename.h”和#include <filename.h>的区别 h@Jg9AM
YU" /p|!1
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 Z#B}#*<C
j
RcE241
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 kG{};Vm
Y 9|!=T%
4'=Q:o*w`
二、头文件的作用 8zpzVizDG
"\O7_od-
加强安全检测 '`|j{mBhG
nu7 R
通过头文件可能方便地调用库功能,而不必关心其实现方式 J
<;xkT1x
%8D>aS U
j}tM0Ug.U
三、* , &修饰符的位置 BWQ`8
k*n~&y: O
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 cc*?4C/t
4].o:d;`/
6dmb
bgO)
四、if语句 b_ak@LYiu
6r`N\ :18
不要将布尔变量与任何值进行比较,那会很容易出错的。 FZn1$_Svr
?ueL'4Mm
整形变量必须要有类型相同的值进行比较 sT"ICooc
TIZ2'q5wg
浮点变量最好少比点,就算要比也要有值进行限制 4r`I)
<8;~4"'a
指针变量要和NULL进行比较,不要和布尔型和整形比较 OdZ/ \_Z
$ZGup"z)
5I,NvHD4
五、const和#define的比较 fkp(M
l"A/6r!Dp
const有数据类型,#define没有数据类型 &Z[+V)6,,
#h^nvRmON
个别编译器中const可以进行调试,#define不可以进行调试 0 K#|11r
C3Q #[
在类中定义常量有两种方式 ?gUraSFU
@2L^?*n=
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; R;pW,]}g,
xjiV9{w
2、 用枚举代替const常量。 z/`+jIB
l^ay*H
Jw@X5-(Cp
六、C++函数中值的传递方式 R[v0T/
9#9bm
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) v0dzM/?*
qbsod
void fun(char c) //pass by value K<:%ofB"S
c5$DHT@N"
void fun(char *str) //pass by pointer (J %4}Dm
]
1pIIX}
void fun(char &str) //pass by reference LwRzzgt
?k4Hk$V
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 dp^PiyL
'DVn /3?X
函数的类型不能省略,就算没有也要加个void ~dEo^vJD
JyTETf,y
p@%Pdx
七、函数体中的指针或引用常量不能被返回 ed/B.SY
F?R6zvive
Char *func(void) ?_d>-NC
%;h1n6=v2
{ 8tR6.09'
J)B3o$
char str[]=”Hello Word”; L!l?tM o
o.NU"$\?
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 &4|]VOf
lqv}~MC
return str; Q2Ey RFT
*5BVL_:~J
} nVWU\$Ft
}v2p]D5n.
函数体内的指针变量并不会随着函数的消亡而自动释放 kVM*[<k
[&*irk
1}|y^oB\-
八、一个内存拷贝函数的实现体 @xBb|/I
q`{@@[/(y
void *memcpy(void *pvTo,const void *pvFrom,size_t size) *!y04'p`<
paD[4L?4Hk
{ fgtwVji
!gRU;ZQU_
assert((pvTo!=NULL)&&(pvFrom!=NULL)); 0 fT*O
y~#5!:Be
byte *pbTo=(byte*)pvTo; //防止地址被改变 rU"AO}6\@
\R@}X cqZ
byte *pbFrom=(byte*)pvFrom; uGXvP(Pg'
,Aq, f$5V
while (size-- >0) B^dMYFelJ
XS@iu,uO
pbTo++ = pbForm++; vFJ4`Gjw(
bt=D<YZk
return pvTo; W3\+51P
8i`T?KB
} @]X!#&2>
E5P.x^
8b,Z)"(U3
九、内存的分配方式 otjT?R2g'
"N%W5[C{
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题 N|>MqH,Bt
aRWj+[[7y
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 |Zn,|-iW
U/q"F<?.c
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 r\b$/:y<e
-6F\=
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 u{WI 4n?
aF"PB
h=
]nIVP
十、内存分配的注意事项 f~=e
}o
GMF~
用new或malloc分配内存时,必须要对此指针赋初值。 "0G)S'
mp(:D&M
用delete 或free释放内存后,必须要将指针指向NULL ?=iy 6q
PB8U+
不能修改指向常量的指针数据 CD?b.Cxai
'g)5vI~'
'zt}\ Dt
十一、内容复制与比较 M#],#o*G
[e. `M{(TB
//数组…… u`+kH8#
/6N!$*8
char a[]=”Hello Word!”; )J\
JAUj
$Ovq}Rexc
char b[10]; K^AIqL8
8.`5"9Vh
strcpy(b,a); <3k9 y^0
Tt0]G_
if (strcmp(a,b)==0) r)qow.+&
gavf$be
{} 'OYnLz`"6
.0y .0=l
//指针…… v>Kv!OY:c
OOus*ooo2
char a[]=”Hello Word!”; ?y* yl
Z
+}#
Ic
char *p; FO|Eg9l
U3>ES"N
p=new char[strlen(a)+1]; .a]av
'! ;Xxe5
strcpy(p,a);
3AuLRI
L{6Vi&I84[
if (strcmp(p,a)==0) R/c-sV
Wzh#dO?7
{} MIAC'_<-e
gAGcbepX
8g_GXtn(z
十二、sizeof的问题 *zPz)3;
5@Xy) z
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 nfr..4,:
i'Q 4touy
char a[]=”Hello World!” |Tl2r,(+R
9[\$\l
char *p=a; Q
S.w#"X[
Z2\Xe~{
count<<sizeof(a)<<end; //12字节 %LdFS~
yD&UH_ 1g
count<<sizeof(p)<<endl; //4字节 AUkePp78
f'M7x6W
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 3:P "6mN
xOpCybmc
void fun(char a[1000]) X9uYqvP\(
s\1c.
{ N^tH&\G\m
!RdubM
count<<sizeof(a)<<endl; //输出4而不是1000 G?{uR6s>#
mt3j$r{_
} a<Ptm(,
w8AHs/'r
M$GZK'%
十三、关于指针 Jp`qE
ulnlRx
1、 指针创建时必须被初始化 PEAo'63$
v4x1=E
2、 指针在free 或delete后必须置为NULL {f)"F;]V
mo3HUXf}8
3、 指针的长度都为4字节 K F`@o@,
%g*AGu`
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 9"~,ha7S$
b6UD!tXp
char *p=new char[100]; jPNm $Y1
4 '6HX#J
strcpy(p,”Hello World”); U
ORoj )$I
[P23.`G~J
delete []p; //注意前面的[]号 <O?UC/$)7
H-.8{8
p=NULL; 4#y
"V/6 nuCo
5、数组指针的内容不能超过数组指针的最大容易。 j5>3Td.
v=I 'rx
如: ENi@R\
p
xT$9M"
char *p=new char[5]; PxHHh{y%c
H#;-(`F
strcpy(p,”Hello World”); //报错 目标容易不够大 x7]Yn'^'
_7"G&nZ0
delete []p; //注意前面的[]号 *^&2L,w
wfxg@<WR
p=NULL; k/ 9S
\L:;~L/
L(2KC>GvA
十四、关于malloc/free 和new /delete %kJ_o*"
JW4~Qwx
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 MdOQEWJ$|
5L}qL?S`x|
l 注意:malloc/free是库函数,new/delete是运算符 zLxO\R!d
"NamP\hj
l malloc/free不能执行构造函数与析构函数,而new/delete可以 hkq[xgX
ZsPT!l,
l new/delete不能在C上运行,所以malloc/free不能被淘汰 t:G67^<3
C"P40VQoo
l 两者都必须要成对使用 ,:QzF"MV
v}$KlT
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 _cY!\'
Kf$%C"
TYQ7jt0=.-
十五、C++的特性 9_z u*
,5_Hen=PI
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 5@6%/='I q
Wm/0Y'$r&k
重载和内联:即可用于全局函数,也可用于类的成员函数; *L3>:],7
bI,gNVN=
Const和Virtual:只可用于类的成员函数; B9RB/vHH
-&u2C}4s
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 &K_"5.7-56
y[s* %yP3l
覆盖是指派生类函数覆盖基类函数 <"g ^V
;oQ*gd
函数名相同; <d GGH
1h.N
&;vy
参数相同; j~eYq
o#-K,|-
基类函数必须有Virtual关键字; y-TS?5Dr]
B%c):`w8]
不同的范围(派生类和基类)。 EhkvC>y
H\\0V.}!
隐藏是指派生类屏蔽了基类的同名函数相同 :1eJc2o
6p
X[m{
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 w~eF0{h
J3oj}M*
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 \o-Q9V
8Q&hhmOnz
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 ZLBv\VQ
{jX
h/`
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 G] -$fz
Lzzf`jN]
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 I-E}D"F;p[
3McBTa!
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: 3d^zLL
W2VH? -Gw
将void Func(A a) 改为void Func(const A &a)。 +)C?v&N
<n iq*
而void func(int a)就没必要改成void func(const int &a); ^FJ=/ #@T
;&Q8xC2
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 P#/k5]g
IS`1}i$1%
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 {%$eq{~m
xF'9`y^]!@
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; t>J 43
ANNfL9:Jy
pJC@}z^cw
十六、extern“C”有什么作用? PK#; \Zw
_7(>0GY
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 aHosu=NK
TbqED\5@9w
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 bDa(@QJ-
#{)=%5=c
i]:T{2
十七、构造函数与析构函数 2f8fA'|O
`B{N3Kxbp
派生类的构造函数应在初始化表里调用基类的构造函数; [HJ^'/bB'
^zv0hGk 2
派生类和基类的析构函数应加Virtual关键字。 NJfI9 L
U[/k=}76
不要小看构造函数和析构函数,其实编起来还是不容易。 seh1(q?Va4
pei-R
#include <iostream.h> MS,J+'2
x:W nF62
class Base kw8?::
<
6b9 oSY-8
{ `+[e]dH
58"Cn ||tF
public: ]de'v
#<V/lPz+
virtual ~Base() { cout<< "~Base" << endl ; } WQ/H8rOs
{=WTAgP
}; CzKU;~D=B
gVM9*3LH6
class Derived : public Base 0oI3Fb;E
6/ir("LK
{ A)/
8FYc
]iewukB4
public: isaDIl;L/
NIcPjo
virtual ~Derived() { cout<< "~Derived" << endl ; } '!*,JG5_
.lVC>UT
}; jM8e2z3
i1]*5;q
void main(void) $Q,Fr;
B
\2(Uqf#_
{ `9a %vN
Fp>iwdjFg
Base * pB = new Derived; // upcast 6-U+<[,x
g9>
0N#<
delete pB; XUT,)dL
GAONgz|ZI
} OOy]:t4 /
!|hxr#q=4
输出结果为: x8I=I"Sp
rQ -pD
~Derived >U\,(VB
:_;9&[H9ha
~Base kwRXNE(k]_
tz&'!n}
如果析构函数不为虚,那么输出结果为 h2g|D(u)
X~ n=U4s}O
~Base $]IX11.m
4.|-?qG
j4j %r(
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 w5 nzS)B:u
MP/6AAt7=|
仿止该头文件被重复引用