模板策略,请大家讨论如下代码结构的利弊、适用场合!

kbase 2008-12-31 02:57:44
模拟代码如下,请先给出 Test() 中的 n1-n8 的值,这种结构在我们实际系统中有用到,欢迎大家就代码结构的利弊、适用场合、替换方法等各方面发表看法!

class Strategy11
{
public:
typedef char KEY;
};
class Strategy12
{
public:
typedef unsigned short KEY;
};

class Strategy21
{
public:
static int Foo(){ return 10;}
};
class Strategy22
{
public:
static int Foo(){ return 20;}
};

class MyStrategy : public Strategy11, public Strategy21
{
};
class YourStrategy : public Strategy12, public Strategy22
{
};

class RootClass
{
public:
virtual int Test1() {return -1;};
int Test2() {return -1;};
};

template<class Strategy>
class BaseClass : public RootClass
{
public:
typedef typename Strategy::KEY KEY;

int Test1() { return sizeof(KEY); };
int Test2() { return Strategy::Foo(); };
};

//////////////////////////////////////////////////
void Test()
{
BaseClass<MyStrategy> d1;
int n1 = d1.Test1();
int n2 = d1.Test2();

BaseClass<YourStrategy> d2;
int n3 = d2.Test1();
int n4 = d2.Test2();

RootClass *p = &d1;
int n5 = p->Test1();
int n6 = p->Test2();

p = &d2;
int n7 = p->Test1();
int n8 = p->Test2();
}
...全文
929 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
kaidiligent0 2008-12-31
  • 打赏
  • 举报
回复
过来学习了,哈哈.
jieao111 2008-12-31
  • 打赏
  • 举报
回复
mark
nineforever 2008-12-31
  • 打赏
  • 举报
回复
To ysuliu
在类的定义内实现的函数默认就是inline的

建议lz将策略做正交分解,避免不必要的使用多重继承
PS:你RootClass的Test2忘记声明成virtual了


class Strategy11
{
public:
typedef char KEY;
};
class Strategy12
{
public:
typedef unsigned short KEY;
};

class Strategy21
{
public:
static int Foo(){ return 10;}
};
class Strategy22
{
public:
static int Foo(){ return 20;}
};

class RootClass
{
public:
virtual int Test1() {return -1;};
virtual int Test2() {return -1;};
};

template <class TypeStrategy,class BehaviorStrategy>
class BaseClass : public RootClass
{
public:
typedef typename TypeStrategy::KEY KEY;

int Test1() { return sizeof(KEY); };
int Test2() { return BehaviorStrategy::Foo(); };
};

typedef BaseClass<Strategy11,Strategy21> MyStrategy;
typedef BaseClass<Strategy12,Strategy22> YourStrategy;

//////////////////////////////////////////////////
void Test()
{
MyStrategy d1;
int n1 = d1.Test1();
int n2 = d1.Test2();

YourStrategy d2;
int n3 = d2.Test1();
int n4 = d2.Test2();

RootClass *p = &d1;
int n5 = p->Test1();
int n6 = p->Test2();

p = &d2;
int n7 = p->Test1();
int n8 = p->Test2();
}

int main()
{
Test();
}
zenny_chen 2008-12-31
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 ysuliu 的回复:]
个人建议,把
int Test1() { return sizeof(KEY); };
int Test2() { return Strategy::Foo(); };

变成内联的

inline int Test1() { return sizeof(KEY); };
inline int Test2() { return Strategy::Foo(); };

假设你在模板类里函数的实现都这么简单。。

这种用法有点像symbian中的瘦模板的实现,减小模板被复制多次后的代码体积。
[/Quote]

嗯。本人就仅对运行时效率发表一下看法。
就楼上仁兄所言,若在这里能够使用内联的话那时自然最好不过,可以大大减少代码体积。
可惜的是Test1()和Test2()都是虚函数,一般情况下可能无法被内联。这确实将会非常遗憾。
你的样例代码将直接导致:
BaseClass<MyStrategy>::Test1()
BaseClass<YourStrategy>::Test1()
BaseClass<MyStrategy>::Test2()
BaseClass<YourStrategy>::Test2()
这四种虚函数实体,当然还将包括它们的虚函数表

就你上面所言“几十种索引类型”,那么后果可想而知了,呵呵。

不过在你系统中使用多态看来是无法避免的,这也就没办法了。
综合考虑来看,还行吧。在这种情况下,如果策略确实量比较大的话,运行效率确实能够高一些。使用多态实际上就是对C语言中的函数列表的一种转换形式。
从管理角度而言,也还不错。
kbase 2008-12-31
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 taodm 的回复:]
你的系统能复杂过linux?linux用C编的,根本就没有模板。
所以,我相信,没有什么迫不得已,只是给自己没有尽可能KISS找个理由而已。
至于它在你们的系统里是不是算一个好的解,那就没有别人可以帮你鉴定了。
冷暖自知。
[/Quote]

这套系统研发了十多年,完全重构当然能轻易找到更好的方案。维护一套系统,不断扩充其功能,不能轻易将其推倒重来。维护很多时候比重新开发要考虑更多的问题,使用更复杂的技术方案。
lightnut 2008-12-31
  • 打赏
  • 举报
回复
没有背景, 让人如何讨论呢?
任何设计的优点, 只能在某一背景下讨论才有意义.
请楼主不吝给出设计的背景吧....
flydream1980 2008-12-31
  • 打赏
  • 举报
回复
学习一下
ysuliu 2008-12-31
  • 打赏
  • 举报
回复
个人建议,把
int Test1() { return sizeof(KEY); };
int Test2() { return Strategy::Foo(); };

变成内联的

inline int Test1() { return sizeof(KEY); };
inline int Test2() { return Strategy::Foo(); };

假设你在模板类里函数的实现都这么简单。。

这种用法有点像symbian中的瘦模板的实现,减小模板被复制多次后的代码体积。
ysuliu 2008-12-31
  • 打赏
  • 举报
回复
呵呵,有道理。。
[Quote=引用 7 楼 taodm 的回复:]
你的系统能复杂过linux?linux用C编的,根本就没有模板。
所以,我相信,没有什么迫不得已,只是给自己没有尽可能KISS找个理由而已。
至于它在你们的系统里是不是算一个好的解,那就没有别人可以帮你鉴定了。
冷暖自知。
[/Quote]
标叔 2008-12-31
  • 打赏
  • 举报
回复
跟着在学习
taodm 2008-12-31
  • 打赏
  • 举报
回复
你的系统能复杂过linux?linux用C编的,根本就没有模板。
所以,我相信,没有什么迫不得已,只是给自己没有尽可能KISS找个理由而已。
至于它在你们的系统里是不是算一个好的解,那就没有别人可以帮你鉴定了。
冷暖自知。
kbase 2008-12-31
  • 打赏
  • 举报
回复
策略的组合可以使用模板来实现,对,更有技巧、方便。
其实,我们系统中采用如题的解决办法,是迫不得已的,我们的系统中有几十种索引类型,支持GBK和UNICODE两种编码。我们并不是为了追求技巧才这么做!
xiaoyisnail 2008-12-31
  • 打赏
  • 举报
回复
进来学习
hhyttppd 2008-12-31
  • 打赏
  • 举报
回复

void main()
{
BaseClass <MyStrategy> d1;
int n1 = d1.Test1();
int n2 = d1.Test2();

BaseClass <YourStrategy> d2;
int n3 = d2.Test1();
int n4 = d2.Test2();

RootClass *p = &d1;
int n5 = p->Test1();
int n6 = p->Test2();

p = &d2;
int n7 = p->Test1();
int n8 = p->Test2();

#define check(op, result) \
cout << #op << "(" << op << ")" << "\t" << " = " << result << "\t"\
<< "\t" << (((op) == result) ? "pass" : "failed" ) << endl

check(n1, 1);
check(n2, 10);
check(n3, 2);
check(n4, 20);
check(n5, 1);
check(n6, -1);
check(n7, 2);
check(n8, -1);
}

class MyStrategy : public Strategy11, public Strategy21
{
};
class YourStrategy : public Strategy12, public Strategy22
{
};


策略的组合可以使用模板来实现


template<class G1, class G2>
class State_T : public G1, G2
{};
typedef State_T<Strategy11, Stategy21> MyStrategy;

kbase 2008-12-31
  • 打赏
  • 举报
回复
在我们的实际系统中,有的地方不用这种策略,无法保证代码重用、一致。
kbase 2008-12-31
  • 打赏
  • 举报
回复
技术交友,欢迎有能力、意愿的朋友加入我们的研发团队!
中国知网(www.cnki.net),诚聘搜索、数据库方向专家,
要求精通 c++。有意者请联系 EMAIL: lchen@cnki.net
taodm 2008-12-31
  • 打赏
  • 举报
回复
太复杂。有过度设计、过度技巧的嫌疑。

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧