2007-2-21 15:39 ak47
C++学习要点

1. 传指针时,我们可以通过指针来修改它在外部所指向的内容。但如果要修改外部指针所指向的对象是不可能的。例如传递外部指针到函数内来分配空间,必须传递指针的指针或指针的引用。7j0t u/z4pc ?'a|U
d1P({$n8tVS pO8Hl
2. char carry[10] = {0}; 编译器会将其后所有的东西都置0;a3^6FhE

7{o3z)e-VD 3. 函数返回值为const时,返回的东西付给一个类型相同的标示后其不能为左值;
b1Q5y W9Q:ny7~Y zy l}4OY,j(y+a
4. const int *i; int const *i; int * const i; 前两个功能相同,说明I所指向的内容不变;最后一个说明指针指向的地址不变,但内容可变。V+Cy;L9}q
)J[J8qE3Jq ZgKD:^
5. 类中的const成员函数。定义为在原型后加const。常量函数不能修改类中的任何属性。但有两种方法可以修改。
Yc Lbg2z
+jt5Ot.J n[g#v a)         {(myclass *)this->member1 = values;}V} {+`-K
0CM^X,ehAc
b)        将一个成员定义成mutable即可被常量函数修改。
/Hd c*bL]*?F;o6dM/AY,w ]N#xim@
6. 类中的常量const 类型的,不能在类中被用来定义数组。而enum {ONE=100; TWO=2};定义的ONE、TWO却可以。通常的enum定义的置分配问题:enum A{ L=9, Z};此时Z的值为10。4v5| qd,J)i0G

FHBk7l(^ 7. 用const定义的int可用来开辟数组,但const定义的常量数组中的元素,不能用来定义数组。
"h`.i)|8uBb d+L/`X:Pb){f
8. 用sizeof计算变量的空间,如果是数组,按实际空间返回;常量字符串(实际上是在静态内存区开辟的变量)sizeof返回比实际长度加一。如果是指针则不考虑它指向的空间大小,仅仅返回指针类型的大小。如果用sizeof计算函数的行参,即使是属组也仅仅返回一个相关类型指针的大小。6VmD)\,RT

$f%iap6Z9r s%T/k 9. 形如int iarray[] = {12, 124, 433};编译器会自动给iarray分配3个元素的长度。元素长度的个数计算公式为sizeof(iarray) / sizeof(*iarray)。
| t6i @;G:td+N7~S 9l4A VED1V
10.         拷贝构造函数:当行参和实参结合时,如果是复杂对象的传值类型,则调用拷贝构造函数生成一个临时对象作为实参,退出函数时,临时对象被调用析构函数释放。当返回值是复杂对象是,也是调用拷贝构造函数来赋值。这就出现构造函数和析构函数被调用次数不相等的情况。拷贝构造函数的原型为A(A&),我们可在类中重载。(缺省的拷贝构造函数是使用位(bit)拷贝方法:浅层拷贝,不拷贝指针指向的内容)。
X0g\:ad .KzK/a4h9l
11.         volatile类型的变量告诉编译器,本变量不需要进行代码优化。在多线程的应用中,我们如果读入一个变量到寄存器,此时时间片到期,去处理其他线程了,在重新获得处理机时,volatile类型告诉处理机,重新从变量读取数据到寄存器,而不是用寄存器数据直接处理,这样可以防止脏数据。l4MA6q9[!y jYlm
$~E\MJ+c\^$mh
12.         class 和struct在一定程度上有相同的功能,只不过前者缺省的成员是私有的,后者在缺省时成员为共有的。故而class不是c++必需的保留字`*^l8\{;](^5Hs
n{)[| dq(\+h {$[
13.         c和c++编译器,对相同的函数名编译后生成的相同的标示不同,故而在引用c的库文件时必须使用extern “C”告诉编译器,它是c的函数,按c的规则编译。通常我们使用的标准头文件已被处理过。r*^#?g-QFBo
4y%M;f\e8EY
14.         #include “filename”; #include <filename>,前者先在当前目录下寻找文件,如果找不到再到系统规定的路径下找,后者直接到系统规定的路径下找。
-WjLh%z$E:oV !i |V \_
15.         任何地方分配的静态变量(static),其生命周期和主进程相同。第二次定义一个已存在的static变量,对变量的内用无影响,但它的可见范围只在定义的范围内。(考研曾作错!)(从静态变量的特性不难理解,类中的static类型是所有对象共享的)GZ.rp ouV
0~\0V'y xs!o
16.         内联函数(inline)在实现上实际和宏类似,在内联函数出现的地方将函数展开来避免函数调用时的出栈、如栈,提高效率。但内联函数的代价是:代码增大。inline函数适合成员函数和自由函数。在类中实现的函数自动为内联函数。inline必须定义到函数的实现上,例如:inline int PlusOne(int) 是无效的。友元函数在类的体内被实现自动变为内联函数。D&o$AI"S`G

i%c(o)MR6S 17.         #include <iostream.h> U@-Nl0wtr&Q0w;}
/Ju t+bV7{6i
#define DEBUG(X) cout<<#X"="<<X<<endl
!g E;g{ _!iG-Y u o4R-e T hzI|5I
其中的#X表示X被当作字符串输出。;C/z,Y g1F'A'|VUc

@9y+g3f-a 18.         assert(0 != 0); 如果assert中的条件为假,则运行期间回退出程序,且报告出错代码的行号。(#include <assert.h>)*MS1IM-D6QO
@F.PdAx!}R!L&` Y
19.         静态对象在main结束或exit()被调用时才调用自身的析构函数。这意味着,在对象的析构函数中调用exit()是很危险的,有可能进入一个死循环中。调用abort()来退出函数,静态对象的析构函数并不会被调用。我们可以用atexit()来指定跳出main或调用exit时要执行的操作,用atexit注册的函数,可以在所有对象的析构函数之前调用。,HT b M/`9Or#s

$Gc%fdcO5i void exit_fn2(void)
v&DX O%~
@ i^7P.k3O2t;I@'` {pz/A6GjJ k9x

g;{'r9K2B(SP    printf("Exit function #2 called\n");q;o B%u]$d3W
/aOyLn g
}     //处理函数+yjYy1e$@B p
9ng Qc+g7z.x
atexit(exit_fn2);
3f,V(oG!?'D
6y J ^$p9t5z;wm*L 20.         全局变量实际上用的是静态存储。静态变量的构造是在进入main之前调用的,在main结束时调用它的析构函数。变量的名字由小范围(c++而言)::B(Kkq6W0N/L:]]

"g2mwLm2Tl@y3~ //*.cpp
\3y3N:H K's t])wivY+k9D
int a; //静态变量,但为 extern int a; 即它是全局的,外部可见的m4n+Gmz

1yt8SG6o u+@m#bKF static int b;       //静态变量,static 和extern相反,只在*.cpp中有效,对其他单元(文件)是不可见的。函数的定义和上面相同。
1E(L(Q] kR P
s,e^HG \$xlR main()m5k AxGd t9ou
1`{w(M&Qd:}XJ2l;N
{     }
2oDi'L6b+M'\;],jR xu/` H8C.|;O;{
类的静态成员变量可以如下赋值:int X::s=23;(在*.cpp中,无论公私都可以)
,OJ&T9d@y}!h M g1X7~p|%X
21.         名字空间(namespace): 定义一个名字空间,然后使用unsing就可以将当前的类型上下文转换名字空间所定地的.
dc4L gPbw
i-HKIai&HI1gV namespace math
-u s K&r,k_
V^.~iPf {
?.d;ze#cf"F[ZB,\c
8zy vcS K+t        enum sign{positive, negative};
$u*FN#jo
{r0Ah klQ j"l uXm!n        class integer{5r N#|;C1Y8_ F-y-h W$~
8K&b7Y5A(z;Jj?8A9r^
       int i;
3[scjdpdU q _,{%@&QB
       sign s;
MPDh2u *iTUx*L#B
       public:3lb8P4Sb)Z7R4E
1]+W]]"B
       interger(int I=0): i(i) {………}
-H`ZA*m-A~
"viE8r"G#od)b+t-MkL        sign Sign() {………},xVJ5k:RF'R.Dy"fe
4{'}$v\z1SG h
       …………………..   {N?cK
b z/gL7^3[
       };//end class
V6J%tIS6li2cs|1j
"r]8w;[{%`4LU interger A, B, C;b c[3FR"nU$v1a
iK%puUa {
interger divide(interger, interger);
Z] K6b Z!eo$u Hb
"@.]"Go9P?5H0Ek9h'] }//no ;
wdgkDH+E7N @l)J+pw_$x,R
M1` BB-P)xa

0WLX%nCg1g'r void q()PV%A4QH4?7j U]

H zXaZ-O {
Y!f&Ak;_ s3QE-i )N&Ank;Z$L"D+R ^
       using namespace math;
_D?haE WX/hB'K0k ul
interger A; //hides math::A
$e N P"v-C*d H'[O5fN2E*T
A.Sign(negative);
(HyJD A/D WR~Nu0]
Math::A.Sign(positive);
gR6sMH$g9E9t R~/vj j z
}
Kd3\[B}FF1{)c;oV
,MH#SIh-A i+E/F 22.         一般对于函数flaot f(int a, int b); 某些c++编译器编译后生成_f_int_int的名字,有些c编译器则生成_f的名字。故在c++中链接c的库函数时要用extern “C”告诉编译器,按c的规则来编译函数。类似的还有extern “C”{#include “myhead.h”},c++还支持extern “C++”{}.0am/};^ni
KY*m9F xP G
23.         在函数调用时,传引用也是将指针压栈。VT3m2\,G}5k
]z'_/}'_]5K0v+x
24.         构造函数、析构函数、赋值构造函数、重载的=,四者的调用顺序:(三种函数都已实现)s}h8_ P b(z
)}2k F dz
a)    X  x;     X  a=x;i/sb6m:A5Q
_ A#h p[
result: K"nw A]hkCD;r

"Z{Y1\(mP?#EO X:construct   0@l(q4}/LX6C*g.r%}
/L2IN VGOGJ
X:copy_struct:` qhmb-n y)U
,`5]8r@oC$y5r1@P
b)    X x;        X a;        a=x;
N&u J Vt%[Q;bD2l +]!jMn0X d;N9e~&G
Result:|9N7b Ge,N4l U'Vw
;mr]r:}W5[y'D}
X:construct
-uxk0BD#[zQ%x
-I&S/Ht8pn X:constructX8bm'G&V-m,o/fp
~){G/v/vd
X:copy_struu)t9W x/s6K] l1v5F3h
)gJq+j$j,i w:B
operator =
6RM~DC7fE?b
SqA"m6QfJm X:destruct @ITXH-Yw ZzjT
YP%x(G@T#T t2| {
如果没有赋值构造函数则结果:5F?YU/_}$Wh

"K#i.k#e @/o q+H[G                     X:construct?`KD,[\ q1bk

.cm:^3N!O_ X:construct)U } XB7}M _V

s*O#X6N#f1NxB operator =
,o1BpC s:MNLY
w&o)O z%\$hJ X:destruct2r{+Jk9`0pC
H/MkYH
(如果直接X a=x;这不掉用一般的构造函数,调用复制构造函数)
Y4N} KB E ?
,T9qNyR)X0wP]}]    指向类的成员函数的指针:设 int X:: a(void){}%S$T^a0C g9?j0V

9dP @*^+b'X`Ep_ X x;TDe"G9Ech
?4}'byr/X1~u
                 int (X:: *pf)(void)= &X::a;DT y e~S%]

AMUu*s].W G m#wI                  (x.*pf)();
"\Jt+v P%C6L 5RM E3d!NN\
指向成员变量的指针: 设int i; 是X的成员变量g)J1@:mH.b
D;F7s%Ul*NdE.ch
                    int X::*pm = &X::i;
i B\`:O"}e|%K Z|.L $qST`` _9B0sd.}
                 X x; K7AC#qkj!x d1Tv
4~C!TB*H5K6~
x.*pm=12;']}-[ m#n|!U

hzMVw8e$t^&|                  X *p=&x;
A7S6Pu(Lg9V'H 4Qc/[@&R"t&d&Z
p->*pm=11;
p+X y X&k}!x
y2`f!vK/\+U![]k 25.         ++的操作符重载7k0g:WP+eb
*zH,[Cp F2p
const X& operator++() //++b;            const X operator++(int ) //b++)fbe.zN PSxy9`
-i3d@ TWy
其中的第二个参数为哑元,永远也不使用到。
5^%oG#L`2pQ4a/K W
K&Y2Pl;J x%B 26.自动类型转换\7loBJry{5u

9d)y0N&J3@c*d a.)       class one{ b} class two{&T(@ P7R$oNj*k} C"|
tE|$o:CihGW g
      public:        one(){}                                          public:       two(const one &){}+\IR2O&jA4w'of b

O3X_RQg2oU S8bC{              };              }; nW/p ]}
*aPVb!`t
void f(two) {}#W|dCC!x
L!TV5t2X/i;t)fX
main(){ one ONE;       f(ONE);     }`2P \bNzZFnU

)uh ?5f3_"wX 此时会调用two中的一个构造函数进行类型的自动转换。但效率不高。可以阻止隐含的类型转换。方法如下:将类two给为z W'?(h:B\;k9yL%K

lu HY.`s0@u+} class two{ public:  explicit two(const one &){} };
N+I&ua,_9t "R6KRC/\B2~b"j A~
explicit只对构造函数起作用。此时必须这样调用函数:f(two(ONE));UG*W2`%f Weo b

^T4E m)c q l"{ 27.    一个理想的string类,它知道如何从string转换到char *:Jr%ZZn

?n.uCU0B9q       class string
ujCy,]:Yc n"U gd*BH
{
!k%@!z VL
,}I;t#^+W a\.s       private:       char *s;+Sx6Dg_r9e;aR"r
Q#ZW gZF:W
       public:
iQMql ~5{bDfX,Ir
               string(const char *S="")-w'fM f`4`
qx2R:|;j8^2q
               {
8b!t |8vx8w !?$Q |\'}4G2CM3[
                       s=new char[strlen(S)+1];
2L `JFd BI
q(IW lq6i                        strcpy(s, S);7WmX n_x2W{&|#d

S:md{$G vOj&qX                }v:T2L&{XT.mT

0r;OTz S3e                ~string(){delete s;},\5e&hBtWu&NS+m

c3ef2\Ki                operator const char *() const {return s;}
.^8FhK[3U2Mk %{B5I7hP
};
V;d0iYXf
*k|0rH!^an v x[      int main(void)
0yn*n*X#Uk\ 3P{,k]!^"u{+?A
     { Q`1W2W:Fv#Y

yf:T!R*V:G v6Y        string str1("lizhihui2");V5g]4DCU

V%n,Nzk%fl        string str2("lizhihui2");i3Q$BqUB`G!{M

.m"So;H)}.B(M5Y)a~-I;\Q C        strcmp(str1, str2); A+ailnQ_@ u
a&N8a PU%O
     }i pdq2u%h ~*`/T
OtnqL(H-Z4{
28.    如果从一种类型到另一钟类型有多种转换方法,则会出错:
_3E(A7U ya R.dGL+f3[!Cl
      classs Y;[hr"t)y9l`yb
A5D*wUl'dl
      class X1X~G}]

'k` p"P4F { Xs$z"`$A7cG
8z+B3T }*Q@`4r1N
             public:      operator Y() const; //convert X to Y
{ls%DO NrB
M_S ^_Z       };%L*d8}@7u^0q

d(p@Wj8y       class Y{{*J(M,D][8v
WAm?ZW*Pf%T8I
             public:       Y(X) ;//convert X to Y
,]ph5@{
"y@1ju%F2B&T G-T       };cWd.a#BjH

9^]%L,y ~&O!m C?qV]       void f(Y);
_Z9O'S9OmBNO$c A%A4M#A1n5C
      main()
\H$f P2OI!L4xE
g*Yk a'QK-[ j3P {
GJl4R1?#d{
2]? O+N j k9Kx5z       X x;'oa\])cS1AO
1\6UV x+c ~U%_
      f(x); //error: ambiguous conversion
9F.a:t6H"ahwc5E S
|a)v)k!Ja'M(b*? }
2Z!VQ.e/l@9kz6P7p hx [DD c
29.删除数组对象: F@c$S|&[5UP rA
W;^0@'ql,^pp
      foo *fp = new foo[100];        delete []fp; 或 delete [100]fp;
o"X;M^.o*{ R~ h?&B U
      使指针更像数组:int *const q=new int[10];这样q不能移动则更像数组。
\cg#a-C
'pU,J-{a7\m3?/\7^Y 30.new堆内存用完时的异常处理器函数
P!dB;^G3J B ^Q1I"}^N :g1C K.c-Z&p
void out_of_memory() {printf(“out of memory!\n”);        exit(1);}
`^ Gy%Y k g+^ *jA@lE&w&tR*_.F}
main() { set_new_handler(out_of_memory); …………….}
Hh(T%v'X{fy
+p5N(c4` `K&m+e%R 31.new和delete的一种全局重载方法
l2t:D+FZ-y
$C}jjeKp$T:i void * operator new(size_t sz)`p"| Gc

6^`Z o k D!b } { dS#g#p!]H9\'fq O6_x:G
7beE-TD
       printf("operator new :%d bytes\n",sz);+u_K4b'Q(l-S
/F]*m|OF
       void *m=malloc(sz);
;Pn?k]q wKa&G
m.LVr#ZD1h9]g        if(!m) puts("out of memory\n");#T'|;R%W%tC%b6@\
"]#j}VODQ
       return m;
5M8NT0|!A.Q'qR _
&x xl*~}-MxC hY }SgqV;y!|

%z3[dg0x5b8nIz void operator delete(void *m)GA#BT8VQj

uw)qb.f`#VwU-Z {
7{*e9S/l$NBU'Mz
'B,Bvlo        puts("operator delete.\n"); C Xn#bF1@~
3X"d6j4tX1Rd
       free(m);k!o"Xo*C:r[$?6NY

of?7rCnJ5M }
M1]2h zOw)v 6\3}'{ |)^T9r
class s
NO Emq:})`+s I$D h x1CU.N
{
"t^ry4nJ lk (x4rnZA;N
       int i[100];b#Fp.C/{^KbO
(|"? P&M;hW
public:
v+d%u t7|!Rk(E
l:U;do#oek @ A4d        s(){puts("s::S()");}J:Y-n,Fw"Yq|Q

#X*oVMPgEqqT)E        ~s(){puts("s::~S()");}
)l_u6A)j/y,NC ;H3~,XqU8O+X%[Q6~ ~Kf
};
idjlU"H ` jmf0i*y4y
int main(int argc, char* argv[])
{(yCn3m'F0T
^o8{9l-x EP.} {
5F3l ~h7z(Ql ut ]]|]
       int *p=new int(23); //operator new :4 bytes
j5L F,v F1c-A T#_
elZlal|@        delete p;                  //operator delete.
$P v$Ef7n^0i(P+~
o A'W}G
*YtF'PV)cY r7os+r}x?|g
       s *pp=new s;           //operator new :400 bytes
0D-`U wS @V3p 2dk%t~9O/a L+bJ&x
       delete pp;                 //operator delete.;{;Wto.gIy

S Xh-Z @9g +|5QN&r5IOm!uh l,L
g3? u9P I~_6b+h
       s*pa=new s[3];       //operator new :1208 bytes, more 8 bytes for array info)@ nNz*r |}[ Q
JVb9ux5Td
       delete []pa;              // operator delete.       (C++Bilder unsupport)&k5P7yH.^[!~

9Y"[^B2TBT$`a        return 0;
mnuC3K Ck1lT H-E*R F#_n
}$rzgz!xaT
'M | od GVtP(Y
缺省的系统new和delete是调用malloc和free来工作的,系统要维护一张内存分配表。分配出去的内存要记住它的大小和起始地址,释放时根据起使地址释放。

2007-2-21 15:39 ak47
32.    重载new在特定的内存上分配空间
x w e!X\.k &Un)pM)v"No
class svms'?-V-c9X#L7[1V

F2rb1S;k0ood7I$s {4a^;{-y6`7yT3R
%ftO3RJ;C
       int i;OM BbIX
:U*E+ds8UH2A
public:
5k-V"| c4F+U)]4m
$O*KXz{-EgT.RI        s(int ix=0){i=ix;}
6X8Sv3x J V1u
iTqMw N!r K}Y w        ~s(){puts("s::~S()");}w~v4]p U7C2f8BJy

4v ]E_m]        void * operator new(size_t  d, void *loc) {return loc;}J;z3Gf)Yf&t
7q1~?$a(Whb#pL
};iW0[Y+gw
.d R;PSAb!G\
int main(int argc, char* argv[])pL\Eo
:a)w}N&~?
{ d@9g"y!~3i
.Y$iX DxB Bw
       int len[10];
PFyG*R7?0B%O .J |G6hd&Rs
       s *ps = new (len+1) s(3412);  4JJF\X^ pgx
Px+L1e%d8Z!n
//第一个函数相当于告诉new从哪里开始分配空间(隐含);e4DGKp(v8A w

'jX1G#A*ii]1ZfmS%r //它的值则是要分配的长度。特殊的分配要注意需特殊的释放。
+j4K{} a\Pa )R*KZ;Nt+uM"fY
       return 0;
*LC2T8X!^ W )h$^8C5o1Gm1}"?
}6sE2g2v&uN;t7J R

9B,onT!M,KLB9yY[_j new 在len的空间上分配空间给s对象。(new重载第一个参数必须为size_t系统会自动传给它一个大小尺寸) a9\\$M L ^7^.i
)T*[m.mU0vo4oZ
33.    跳转函数setjmp、longjmp
]G{'PC @G$EGG ZhZkp]
void OZ() ziF#LgQ \ P

w?t0`IH+@ aL {
M [/s:p} l0|5O7s*T /A u\a&}
       printf("there 's no placelike home\n");!A v+[O5Q"S
(^E x;`3vIM2U
       longjmp(kansas, 47);C!cn5Z@%`0J(@
$Vk V&nZ:|EO
} Uv'e7K:h?
P5s1L]ty8t6OM"c6F
jmp_buf kansas;3VBg%wO{ pMy~

*^!L5_*g/eE.d int main(int argc, char* argv[]);caeXZ
H%oL-\RW
{ R?|4k Z0u

%@ R%W5Oc        if(setjmp(kansas)==0)  OZ();
@j4[SxI
e:E1^"{8b ?ob        else       printf(" I have a dream..\n");hGj"^:I7C;Q
$[k _Y(k'S'u u
       return 0;
H2pe^+e^ \&KMx8s Hg/w
}//执行完OZ()后,会立即跳转到printf(" I have a dream..\n");执行
t ug8^2p#}G'A?\;]
r0t uvS;U+H8Z$q setjmp()是一个特别的函数,当被调用的时候,它吧当前的进程状态的相关信息放到buff中,并返回0;如果使用longjmp对同一个buff操作,这就像再次从setjmp中返回,即正确弹出setjmp的后端。这时返回值对于longjmp是第二个参数,所以能发现实际上从longjum中返回了。
l ?/\"QL(M_
1P/L4R$B(Nf6B 34.    异常定制和抛出? Ut|,VJ|7n

$M;gv7`&@ class up{};%^9M-~ai/K'DF

U/w R$Y*k {z class fit{};)ueI f N(c5?5a&iD

;EG/SR(F void g();
"o0k#Zu W? { l^
!l3My)CY"V^]G)O void f(int i) throw (up, fit)J8f"G d b/IFv
!pQF9`LqI Y8M
{p KnsmO

;`n9~3]}l5x        switch(i)N:[0g}vs

5mRhB@+oq-p:j9?        {
-~(h@Jt&S&y~%R
JfG K[:r#n&K                case 1: throw up();P"I2NH `$@@;gX#H(\
B"h$w,jN @-Ts
               case 2: throw fit();
3Ta7} I1lL/F,O
s.e0J K;BxFns.M        }
6@)ZgouLr
$sbg5Cd;H        g();
&\3j$qq#UF3}B,\ 2o-_2S,LH$` FtT ]
}9BF7Q$HHD)VFX

y5I8~ L0Z'N? void g(){throw 47;}
Q k*?1Em1n%j)h E-[Sc w8_9t T
void my_unexpected()LUXH/j,z9T&\

1w[jh3@| l C {l:l \#O/]-R b6s
;j]9}O;[aQ"[,V
       printf("unexpected handle!\n");
LA7`"uj8AJBc)a[ -v9{-pv%WuC/b
       exit(1);x9d.^M6RhL

YNz @1NYVu }5FYrgg*da7Z
;k ~d*l mY
int main(int argc, char* argv[])7a4b:}.l#UE7u
se"p3j0A6bH?R
{
d-`8C[~4_&L us*K8eT:FW
       set_unexpected(my_unexpected);]'v7A,}W'LN"f%[Ye
D2c R0vwe-N PMt
       for(int i=1;i<=3;i++)hu"I O(KeS bL R(e;A

?c3Q8rw-K&k        {
{,wwU7\;R{
z8N8F!{ZpT%TL]i                try{ f(i);}u:KWBq K7}

n)w;|vO sL%p                catch(up)  {printf("catch up\n");}5])@ ik~ u
)e!x:G/T4fz zHJ
               catch(fit){printf("catch fit\n");}
y w"dBq3B/E4x6Q
:LemR7Cs^)W        }
D h x _Hj#y/^
jfr8OW x%y        return 0;
fb@*O;Ef;[,vW?
1DzU6x]6N)V9_ }
q af'nOv-B 'bPH7bd:E9Y$]6YJ
set_unexpected设置处理系统不认识的异常情况(缺省是中断)(异常处理安装器缺省指向terminate())。上面我们定义了up、fit两种异常抛出类,并抛出了这两种异常,来捕获。抛出异常时也生成了异常的一个对象。Catch(…){}捕获所有异常。( 但失去了截获的异常类型)y-A;LCHG)mZ

F;["{,W"~$\A 35.    当有未被捕获的的异常时,系统缺省调用terminate(),它调用abort()函数直接从进程中退出,此时静态全局变量的析构函数未被调用。可以使用set_terminate来安装自己的terminate函数,用法和上面的几个安装起一样。他返回的typedef void (*terminate_handler)();为老的处理器指针。
?$KzA)y!q Y4V \!B ke,_*J#XS0b
       当一个构造函数在分配资源时,如果这时有unexpect异常到达,系统会结束而不会调用析构函数来释放已 分配的堆内存。:{aPR4v"e/v d7R

} ?(?g xH Hp8i 36.    运行期间的类型判定(run-time type identification, RTTI)
{/^BBe`CC)u v $A3Ea-rwI
a.) 编译器实现。
U/EG!e$Cy
9k`p,w9\A)l 使用函数typeid(objname).name()就可得到函数的名字。实际上typeid()返回全局typeinfo类的常量对象的一个引用。使用before来判断一个对象是否在另一个对象前定义。b%X#\l&Mm2Q
c2h&wL*`2Ve
fit ft;
5O"qwk7v;^px"{ .@+O3V N'o'ol`.ba
       up u;hH#n#_-` {PT

]-X z3d J1pTY!w        if(typeid(ft).before(typeid(u))) printf("lzh\n"); //is true ua is/k!Tn

{pa*h5kS b). 安全方法向下映射法
,O8b/{e xQim Jqh] @/Dl!i
        C* pc = dynamic_cast<C*>(pd);   // ok: C is a direct base class3h X,k[-G$DQ
                                         // pc points to C subobject of pd
gY7{+~8]l l E            判断pd时不是一个C*类型的对象,如是则返回一个指针,否则返回NULL.是通过试图指派法来断定的,与第一种方法不同。

2007-2-28 17:15 longjinzhe
顶一下
H${Y%zT:p 我正在学这个

2007-2-28 17:25 jllmh1987
不错不错,挺实用的,顶一下

2007-7-10 10:35 浮烟浪子
顶一下
Zzs/`*\+@#o6PU.P 我正在学这个

2007-7-11 00:50 chen0012jie
;P ;P ;P ;P

2007-8-6 22:21 小小的我
出自

出自中国教育信息资源网[url]www.edu2edu.com[/url]

2007-8-20 10:45 ffzhzhll
谢谢分享!!
Wk7o X4Ijd%` 非常支持!!

2007-8-20 14:17 红影
C++学了都丢了郁闷

2008-2-29 00:42 ericdk
多谢楼主!
9ygC4zT3i 多谢楼主!

2008-3-12 17:17 huangph
总结很精辟!!!

2008-3-19 19:35 bwlovesjp
好东西,顶一下!
4u,d%B\Q!Ek0X 正在苦学!

2008-3-27 16:06 sanskyking
顶!!顶下!!!:victory: :victory:

2008-4-8 15:27 bunjee
温故而知新,好多东西都忘了啊

2008-4-26 18:19 icejiesky
刚刚接触C++
v C`6t%Bb 还看不懂那么多

2008-10-16 09:59 kingsun555
就第一条LZ没有真正领会值传递和引用传递!` sU0C1u'fP1U

G%}*RQ:Tc'T$Y S 在C 里面只有值传递,传指针也是值传递,所以第一条后面那些话就不难理解了!

2008-10-25 21:01 ixix
谢谢楼主分享,对我很有帮助

2008-11-8 19:38 cuh2o
好好学习,天天向上!!

2008-12-24 09:40 yi-tanki
不错,很有帮助。谢谢

页: [1]
查看完整版本: C++学习要点


Powered by Discuz! Archiver 5.0.0  © 2001-2006 Comsenz Inc.