闲人草堂

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

这是我这几天倒腾wii的一点心得,贴出来晒晒,不足之处请大家批评指教啊。

需求:有一个类Base,Base::fun()在不同平台下的实现不同(可能依托于第三方库),问题是,如何才能让我在调用Base的时候,不用区分平台,即达到一次coding,处处可编译通过?

1 class Base
2 {
3  public:
4 void fun();
5 };

解法1:

  最简单的方法,就用这套接口在不同平台上写好实现,编译成静态库或者动态库,然后一个头文件,一个lib走遍天下。

解法2:

     稍微折腾一点,使用抽象类:

1 class Base
2 {
3 public:
4 virtual void fun();
5 };
6
7  class windows_v : public Base
8 {
9  public:
10 virtual void fun();
11 };
12
13  class linux_v : public Base
14 {
15  public:
16 virtual void func();
17 };

    那在程序中如何使用呢,直接 Base *b = new windows_v,或者Base *b = new linux_v, 还是没达到一次coding,处处编译的目的。咋办,这里有个有效但是丑陋的方法,相信你也想到了,宏替换!譬如:

1 #if defined(_WIN32) || defined(_WIN64)
2 #define platform windows_v
3  #else
4 #define platform linux_v
5  #endif

然后  Base *b = new platform 解决。

解法3:

     解法2其实算不得跨平台,写出来纯粹是凑数。解法3要展示的还是跟抽象类有关。

1 class Base
2 {
3 public:
4 virtual void fun() = 0;
5 static Base* create();
6 void Destroy(){delete this;}
7 };
8
9 class windows_v : public Base
10 {
11 public:
12 virtual void fun();
13 };
14
15 class linux_v : public Base
16 {
17 public:
18 virtual void func();
19 };
20
21 Base* Base::create()
22 {
23 #if defined(_WIN32) || defined(_WIN64)
24 return new windows_v;
25 #else
26 return new linux_v;
27 #endif
28 }
29
30  int main()
31 {
32 Base *b = Base::create();
33 .....
34 b->Destroy();
35 return 0;
36 }

  Base 是个纯抽象类,只定义接口,不能实例化。所以定义了create()函数类动态创建实现类的对象。入口函数可以是全局函数,但最好是静态成员函数。

解法4:

    解法3已经较好的实现了跨平台,但是由于使用了虚类,肯定会对性能带来一些影响。那么可以换种别的方式,即不使用继承。如果觉得void* 太危险可以使用boost::any,这个其实是用模板实现的动态绑定,对性能影响不大。这种方法还能进一步扩展,可以接受字符串来决定用哪个版本的实现类来赋给imp。

1 class Base
2 {
3 public:
4 Base();
5 protected:
6 void * imp; // boost::any imp;
7   };
8
9  class imp_windows_v
10 {};
11
12 Base::Base():imp(new imp_windows_v)
13 {}

总结:

     这几种都是我这几天查找资料总结出来的,如果还有其他一些更智能更简洁的方法,请给我发邮件jtf198711@gmail.com。

     经此一役,我深切体会到,程序员必须是会偷懒的人。只有时刻想着以更高的效率,更短的时间完成工作的人,才不被机器所役。

     与君共勉!

posted on 2011-06-09 23:29  闲人草堂  阅读(842)  评论(2编辑  收藏  举报