一、#include “filename.h”和#include <filename.h>的区别 qz"}g/;?
Lz
|?ek7Q
#include “filename.h”是指编译器将从当前工作目录上开始查找此文件 1XrO~W\=
e2AX0(
#include <filename.h>是指编译器将从标准库目录中开始查找此文件 5Y.)("1f}f
j@AIK+0Qc
5GI,o|[s6
二、头文件的作用 D@,6M#SK
>
$O]Eu!
加强安全检测 w x]0p
4svBzZdr
通过头文件可能方便地调用库功能,而不必关心其实现方式 HCIU!4rH
_mj,u64
7!$Q;A
三、* , &修饰符的位置 WQx?[tW(U
c/:b.>W
对于*和&修饰符,为了避免误解,最好将修饰符紧靠变量名 ~Zun&b)S
5-FQMXgThc
;nI] !g:
四、if语句 F3y9@dA]
S50k>_a;
不要将布尔变量与任何值进行比较,那会很容易出错的。 zUt'QH7E.
EB0TTJR?#
整形变量必须要有类型相同的值进行比较 ]RZ|u*l=x
_F4Ii-6
浮点变量最好少比点,就算要比也要有值进行限制 Wjo[ENHM
vt/x
,Y
指针变量要和NULL进行比较,不要和布尔型和整形比较 cb@?}(aFl
](Xb_xMf
%@<8<6&q
五、const和#define的比较 fnpYT:%fG
EH-sZAv
const有数据类型,#define没有数据类型 `jDTzhO~
0 3L]
个别编译器中const可以进行调试,#define不可以进行调试 %p Ynnfr
R a O-H
在类中定义常量有两种方式 MOQ6:
|-b#9JQ[A
1、 在类在声明常量,但不赋值,在构造函数初始化表中进行赋值; *2ZjE!A
N&.H|5
2、 用枚举代替const常量。 9#23FK
Yc`o5Q\>
Fh)IgzFj
六、C++函数中值的传递方式 0XOp3
-$t{>gO#Y
有三种方式:值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference) -m\u
Wt*cIZ
void fun(char c) //pass by value u^^vB\"^
kq?Ms|h
void fun(char *str) //pass by pointer nxO"ua
~jWn4
\
void fun(char &str) //pass by reference L{#IT.
%gInje
如果输入参数是以值传递的话,最好使用引用传递代替,因为引用传递省去了临时对象的构造和析构 t DO=P
c
<h!_>:2L
函数的类型不能省略,就算没有也要加个void =R^%(Py
O24m;oHM
99]R$eT8
七、函数体中的指针或引用常量不能被返回 'HO$C,1]
kF3k7,.8&
Char *func(void) d.[8c=$
#?RU;1)Cw
{ 2\R'@L*
_1!7V3|^
char str[]=”Hello Word”; xn?a. 3b'
m1j*mtu
//这个是不能被返回的,因为str是个指定变量,不是一般的值,函数结束后会被注销掉 QpF;:YX^3
R$EW4]j
return str; 2d>z1%'
H(H<z,$}T
} Oylf<&knF\
M#ZcY
函数体内的指针变量并不会随着函数的消亡而自动释放 #9=Vg
'%>=ZhO
:vYYfs&
八、一个内存拷贝函数的实现体 E}%B;"b/Tj
{WJ m
void *memcpy(void *pvTo,const void *pvFrom,size_t size) dSLU>E3g
;Y)w@bNt@
{ bAdn &
ov|d^)'
assert((pvTo!=NULL)&&(pvFrom!=NULL)); {5A2&
J.3u^~zy
byte *pbTo=(byte*)pvTo; //防止地址被改变 <3L5"77G6
bs+f,j-oBN
byte *pbFrom=(byte*)pvFrom; I.I`6(Cb
)i6mzzj5
while (size-- >0) .[YuRLGz
]GUvV&6@(
pbTo++ = pbForm++; ''|W9!
f<GhkDPm>?
return pvTo; Yh7rU?Gj
}?lrU.@zg
} sm9k/(-
_qU4Fadgm
C=-=_>Q,L<
九、内存的分配方式 3W V"U
zlyS}x@p
分配方式有三种,请记住,说不定那天去面试的时候就会有人问你这问题
3Nl <p"=
evenq$
H
1、 静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。 %]\kgRr
#+JG(^%B
2、 栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。 4d"r^y'
S Q@y;|(
3、 堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。 x;w6na
tE.FrZS
G`+T+
十、内存分配的注意事项 ag;Q F
qjc8fP2
用new或malloc分配内存时,必须要对此指针赋初值。 Y&`=jDI
W'els)WJ|x
用delete 或free释放内存后,必须要将指针指向NULL hC:n5]K
vjLJinJ/
不能修改指向常量的指针数据 vp1941P
XWDL5K
Ltv]pH}YN
十一、内容复制与比较 \Bz_p'[G
"7U4'Y:E
//数组…… 1f%1*L0>@
T
_r:4JS
char a[]=”Hello Word!”; oVnvO iAc
60P<4
char b[10]; 1}S S+>`
rUwZMli
strcpy(b,a); K'55O&2
#:jHp44J
if (strcmp(a,b)==0) :1 ^LsLr5
><RpEnWZ<
{} G, 44va
^/uA?h:]\
//指针…… ~3^
8>d/
8Pfb~&X^Ws
char a[]=”Hello Word!”; Y5f1lUT
2iHUZzz\
char *p; !NIhx109q
B|Du@^$
p=new char[strlen(a)+1]; fJ5iS
I?]ohG K
strcpy(p,a); @#<D ^"
()2I#
if (strcmp(p,a)==0) |rY1US)S
V08?-Iz$
{} gK_Ymq5>"M
Jlri*q"hE
6wPaJbRtaM
十二、sizeof的问题 EH$1fvE
%fc!2E9|
记住一点,C++无法知道指针所指对象的大小,指针的大小永远为4字节 ng[Ar`
.rO]M:UY
char a[]=”Hello World!” {mm)ay|M
[I0:=yJ+
char *p=a; C'G/AU
6RG)`bu
count<<sizeof(a)<<end; //12字节 iyA'#bE-
VQ"hUX8
count<<sizeof(p)<<endl; //4字节 :=}BN
.@2m07*1
而且,在函数中,数组参数退化为指针,所以下面的内容永远输出为4 XQ#;Zs/l
v;BV@E0}x
void fun(char a[1000]) Ld\R:{M"
t=rEt>n~L
{ j -0z5|*KE
lyIl-!|
count<<sizeof(a)<<endl; //输出4而不是1000 t!* ?dr
kv]~'Srk
} Z"Zmo>cV4
%huRsQ%}
+Um( h-;
十三、关于指针 I*%-cA%l
G(Lzf(
1、 指针创建时必须被初始化 ,f<?;z
vmi+_]
2、 指针在free 或delete后必须置为NULL bT\1>
4<9=5 q]
3、 指针的长度都为4字节 BYpG
_?<|{O
4、释放内存时,如果是数组指针,必须要释放掉所有的内存,如 7OC#8,
jDKO}
bQ
char *p=new char[100]; W_||6LbZy
a!ud{Dx
strcpy(p,”Hello World”); 4Z1ST;
vY4\59]P
delete []p; //注意前面的[]号 %WSo b@f8
s&A}
h
p=NULL; mi
ik%7>W
@"hb) 8ng
5、数组指针的内容不能超过数组指针的最大容易。 nePfuG]Q
N<|@ymi
如: kEJj=wx
N+++4;
char *p=new char[5]; ! _f9NK
YbR!+ 0\g
strcpy(p,”Hello World”); //报错 目标容易不够大 |P[w==AAf
,eOB(?Ku
delete []p; //注意前面的[]号 C+'/>=>a.
vo`2\R.
p=NULL;
05z,b]>l
kr+D,h01
6tB+J F
十四、关于malloc/free 和new /delete E;,u2[3
$g/SWq
l malloc/free 是C/C+的内存分配符,new /delete是C++的内存分配符。 .}&`TU
}
uO);k5H
l 注意:malloc/free是库函数,new/delete是运算符 q_TRq:&.
XJ;D=~
l malloc/free不能执行构造函数与析构函数,而new/delete可以 ?:
N@!jeJ
Hx#;Z
l new/delete不能在C上运行,所以malloc/free不能被淘汰 ahuGq'
?/BqD;{?I
l 两者都必须要成对使用 K$>%e36Cc
9}l33T4T
l C++中可以使用_set_new_hander函数来定义内存分配异常的处理 .>CPRVuVI
H!?c\7adX
,.rs(5.z8/
十五、C++的特性 !HrKXy0{
'L
8n-TyL
C++新增加有重载(overload),内联(inline),Const,Virtual四种机制 }&/o'w2wY
qo p^;~
重载和内联:即可用于全局函数,也可用于类的成员函数; B$-R-S6
&7<TAo;O
Const和Virtual:只可用于类的成员函数; c0PIc^R(@
|*:'TKzNS
重载:在同一类中,函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数,必须用全局引用符号::引用。 TX$r`~
JM=JH
51`
覆盖是指派生类函数覆盖基类函数 GYJ80k|
\!>3SKs(e
函数名相同; *#E
FsUw
6,)[+Bl
参数相同; Q
7
~T9/#-e>BF
基类函数必须有Virtual关键字; QFw +cy
K!:azP,bZ
不同的范围(派生类和基类)。 ?6Jx@ Sh
'{E@*T/<.
隐藏是指派生类屏蔽了基类的同名函数相同 8WtsKOno
X<i^qoV
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。 W=vG$
6`O.!|)
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏。 TFH \K{DM
mk1bcK9
内联:inline关键字必须与定义体放在一起,而不是单单放在声明中。 SNfr"2c'h~
Px$/ _`H
Const:const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 ?,p;O
+,2:g}5
1、 参数做输入用的指针型参数,加上const可防止被意外改动。 )T';qm0w
RMK"o?
2、 按值引用的用户类型做输入参数时,最好将按值传递的改为引用传递,并加上const关键字,目的是为了提高效率。数据类型为内部类型的就没必要做这件事情;如: 2HpHxVJ
vk+VP 1D
将void Func(A a) 改为void Func(const A &a)。 k,'L}SK
87Oad@FOr
而void func(int a)就没必要改成void func(const int &a); m5L-67[sB
+g` 'J$
3、 给返回值为指针类型的函数加上const,会使函数返回值不能被修改,赋给的变量也只能是const型变量。如:函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。 )\_:{ c
f%Ns[S~ r
4、 Const成员函数是指此函数体内只能调用Const成员变量,提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。 _jJPbKz
hn^<;av=
Virtual:虚函数:派生类可以覆盖掉的函数,纯虚函数:只是个空函数,没有函数实现体; sp#p8@Cj
/]=C{)8
wp#'nO
十六、extern“C”有什么作用? L%BNz3:Dt
TatpXN\
Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “c”后,C++就能直接调用C函数了。 >SML"+>
Anscr
Extern “C”主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern “c” 关键字即可。 [K9'<Qnu
KAC6Snu1
mX\TD0$d
十七、构造函数与析构函数 n1~o1
xgpi-l
派生类的构造函数应在初始化表里调用基类的构造函数; fBalTk;G{U
z8QAo\_I(
派生类和基类的析构函数应加Virtual关键字。 :|_'fNd+!
&=#[(vl
不要小看构造函数和析构函数,其实编起来还是不容易。 >_o}
X *&[u7No
#include <iostream.h> E_k$W5
'SCidN(n
class Base ~Q?a|mV,
WOQP$D9
{ Pf|siC^;s~
hCCiD9gz
public: }2(,K[?
JQV%fTH S
virtual ~Base() { cout<< "~Base" << endl ; } 94+KdHAo^M
wT `a3Ymm
}; Q7R~{5r>W
9/hrjItV
class Derived : public Base OlAs'TE^
SF&BbjBE0
{ *"D3E7AO
gUxP>hB
public: ? i( %
>}!mQ pAO
virtual ~Derived() { cout<< "~Derived" << endl ; } :X.b}^ Z(
+VCGlr
}; b+@JY2dvj
0|$v-`P$
void main(void) CPP`
qt%f
%K\?E98M
{ R(2tlZ
Fe]B&n
Base * pB = new Derived; // upcast x*?x=^I{
Rn{iaM2Y<
delete pB; : y5<go8e
kBYNf =
} [* @5\NWR}
;k7xMZs
输出结果为: NXNY"r7~
^zt-HDBR_
~Derived ;cPy1
>)spqu]
~Base !OA]s%u
!|O~$2O@
如果析构函数不为虚,那么输出结果为 U7oo$gW%|T
i|T)p_y(!a
~Base r.#t63Rb
5$wpL(:R(
:|Ad:fEs
十八、#IFNDEF/#DEFINE/#ENDIF有什么作用 DTaN"{
89\n;5'f4
仿止该头文件被重复引用