设为首页 加入收藏

TOP

完成C++不能做到的事 - Visitor模式(一)
2015-11-21 01:02:57 来源: 作者: 【 】 浏览:5
Tags:完成 不能 做到 Visitor 模式
昨晚做完了一个非常困难的任务并送给美国同事Review,因此今天只需要根据他们提出的意见适当修改代码并提交,一周的任务就完成了。剩下的两三天里,我就可以有一些空余的时间看看其它资料来继续充实自己了。
?
  打开Review Board,可以看到我的代码已经被标记为可以提交,但是下面所留的注解引起了我的注意:
?
  “Great job! With this solution, we can start our integration work and perform testing earlier. One thing is that we have used several “instance of” in the overrided function. That’s double dispatch, an obvious signature for using Visitor pattern. We can switch to that pattern in our future work.”
?
  Visitor模式我知道,但是Double Dispatch是什么意思?我打开了搜索引擎,找了几篇有关Double Dispatch的介绍性文章开始读了起来。
?
?
?
Double Dispatch
?
  当然,对Double Dispatch描述最为清晰和准确的还是在Wikipedia上:
?
  In software engineering, double dispatch is a special form of multiple dispatch, and a mechanism that dispatches a function call to different concrete functions depending on the runtime types of two objects involved in the call. In most object-oriented systems, the concrete function that is called from a function call in the code depends on the dynamic type of a single object and therefore they are known as single dispatch calls, or simply virtual function calls.
?
  而在该段文字的最后,我看到了一个再熟悉不过的名词“virtual function”。一看到这个词,我脑中就开始回忆对虚函数进行调用的步骤:在调用虚函数的时候,C++运行时将首先查找对象所对应的虚函数表,然后根据虚函数表中所记录的地址来调用相应的虚函数实现。由于虚函数表是与类型相关联的,因此对虚函数进行调用所执行的逻辑就与对象本身的类型相关。
?
  而Double Dispatch则需要和参与函数调用的两个对象相关。于是我想:那通过为类型添加一个函数重载,不就可以实现Double Dispatch了么?我打开Visual Studio,并在其中写下了如下的代码:
?
?
?1 // 普通汽车,折扣为0.03
?2 class Vehicle
?3 {
?4 public:
?5 ? ? virtual double GetBaseDiscountRate() { return 0.03; }
?6 };
?7?
?8 // 由于是奔驰特销商,因此可以得到更大的折扣
?9 class Benz : public Vehicle
10 {
11 public:
12 ? ? virtual double GetBaseDiscountRate() { return 0.06; }
13 };
14?
15 // 普通的销售人员,只能按照公司规定的折扣进行销售
16 class Sales
17 {
18 public:
19 ? ? virtual double GetDiscountRate(Vehicle& vehicle)
20 ? ? {
21 ? ? ? ? return vehicle.GetBaseDiscountRate();
22 ? ? }
23?
24 ? ? virtual double GetDiscountRate(Benz& benz)
25 ? ? {
26 ? ? ? ? return benz.GetBaseDiscountRate();
27 ? ? }
28 };
29?
30 // 销售经理,可以针对奔驰提供额外的优惠
31 class SalesManager : public Sales
32 {
33 public:
34 ? ? virtual double GetDiscountRate(Vehicle& vehicle)
35 ? ? {
36 ? ? ? ? return vehicle.GetBaseDiscountRate();
37 ? ? }
38?
39 ? ? virtual double GetDiscountRate(Benz& benz)
40 ? ? {
41 ? ? ? ? return benz.GetBaseDiscountRate() * 1.1;
42 ? ? }
43 };
44?
45 int _tmain(int argc, _TCHAR* argv[])
46 {
47 ? ? // 有两辆车需要销售,一辆是普通轿车,而另一辆则是奔驰
48 ? ? Vehicle& vehicle = Vehicle();
49 ? ? Vehicle& benz = Benz();
50?
51 ? ? // 向普通销售询问这两辆车的折扣
52 ? ? Sales* pSales = new Sales();
53 ? ? double rate = pSales->GetDiscountRate(vehicle);
54 ? ? cout << "Sales: The rate for common vehicle is: " << rate << endl;
55 ? ? rate = pSales->GetDiscountRate(benz);
56 ? ? cout << "Sales: The rate for benz is: " << rate << endl;
57?
58 ? ? // 向销售经理询问这两辆车的折扣
59 ? ? SalesManager* pSalesManager = new SalesManager();
60 ? ? rate = pSalesManager->GetDiscountRate(vehicle);
61 ? ? cout << "Sales Manager: The rate for common vehicle is: " << rate << endl;
62 ? ? rate = pSalesManager->GetDiscountRate(benz);
63 ? ? cout << "Sales Manager: The rate for benz is: " << rate << endl;
64?
65 ? ? return 0;
66 }
?
  点击运行,答案却不是我想的那样:
?
?
?
  啊,销售经理并没有提供额外的折扣。这可是个大麻烦。启动Visual Studio的调试功能,我看到了语句“pSalesManager->GetDiscountRate(benz)”所调用的是SalesManager类中定义的为普通汽车所定义的重载:
?
?
1 class SalesManager : public Sales
2 {
3 public:
4 ? ? virtual double GetDiscountRate(Vehicle& vehicle) <----传入的参数的运行时类型是Benz,却调用了为Vehicle定义的重载
5 ? ? {
6 ? ? ? ? return vehicle.GetBaseDiscountR
首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇LeetCode 1 Two Sum 题解 下一篇hdu 1261 字串数 排列组合

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: