float collect(Account& item) {
if(g_specialAccount.IsSpecial(item.AccountType())==false)
return 0;
float result(0);
Account::child_vect& children=item.children();
if(children.size==0
) //最明细科目,没有子科目
return item.ammount();
Account::child_vect::iterator ib(children.begin()), ie(children.end());
for(; ib!=ie; ++ib)
{
result+=collect(*ib);
}
}
然后, 把collect编程模板,Account换成T,所有的item有关的成员调用都改为delegate,把非依赖性的类型,变成依赖性的。于是就变成了:
template<typename T, typename Pred, typename Sub, typename M>
typename M::return_type collect(T& item, Pred p, Sub s, M m) {
if(p(item)==false)
return 0;
typename M::return_type result(0);
T::child_vect& children=s(item);
if(children.size()==0)
return m(item);
T::child_vect::iterator ib(children.begin()), ie(children.end());
for(; ib!=ie; ++ib)
{
result+=collect(*ib, p, s, m);
}
return result;
}
这样的耦合性已经非常小了,残存的耦合性是子节点容器,依赖于T必须存在一个类型或类型别名,是一个标准容器。以及返回值类型依赖于M定义的返回类型。我觉得这应该是必要的约定。
完毕,烦请各位老大指正。
On 9月19日, 下午3时12分, pongba <pon...@gmail.com> wrote:
> 上次的讨论 <http://groups.google.com/group/pongba/t/e553a21476ba2ebd>真过瘾啊:-)
> 我把大家的意思总结了一下,接着讨论!
1. 目前的 C++的 GP 实现, 好像是有一个 c++ 编译器可以从 lib 里面提取模板进行实例化的, 是不是 g++? VC 一定
是需要头文件的, 这样, 一点改掉就会引起所有的程序重新编译, 再加上 c++ 的编译速度, 这个比较讨厌.
2. 项目的分工需要先定义各个模块之间的 API, OOP 的话, API 用 interface 来定义即可, GP 怎么办 ?
模糊记得以前看到一篇文章(是不是 effective c++? ), 讲到 stack 的API 设计, 如果将 pop 和 get
current value 两个东西分开, 会容易导致异常不安全还是什么地, 记性不好, 忘了.
On 9月19日, 下午9时45分, pongba <pon...@gmail.com> wrote:
> 其实这里还有一个问题,就是当出现一组delegate的时候。比如Iter这个concept就有一组delegate(++,--,*等等)。这时客户类就 不能直接省事的delegate了,往往还是要adapter一下。
另外,你说的是 boost 的那个 new-style 迭代器?这也是我很感兴趣的地方,不知道能不能进 C++0x
oldrev <oldrev(at)gmail(dot)com>
Regards
>>> 引用的文字:
oldrev <oldrev(at)gmail(dot)com>
Regards
>>> 引用的文字:
我弄反了, 是弹出和取值混合的话, 无法涉及出异常安全的 API, 还是应该设计正交的 API 才对.
> > STL的Iterator分类体系其实就是一个接口体系。一旦这个体系建立起来了,就有了依赖性。STL的Iterator体系被证明分类分得并不好,把遍历方 式跟取值的方式混在一起了,违反了正交性法则。- 隐藏被引用文字 -
>
> - 显示引用的文字 -
我做过 函数指针耦合, 这样做, 不必放弃类型安全:
typedef struct for_cls_t { } cls1_t;
cls1_t * getInstance(...);
void draw(cls1_t, ....);
你传给 draw 的东西, 只能从 getInstance 中获得, 别的地方你取不到.
draw 里面会将 cls1_t 再强制转换成它知道的具体类型来调用 --- 我以前做的时
候, 这里是一个类对象, 为 api 的每个 c 函数写了一个 wrapper function, 有
点烦, 不过接口看起来很简单, 所以我认了.
要说强制类型转换, 在这里用似乎也不是很邪恶.
Huafeng Mo 写道:
> 但是,SP的弱耦合不是没有代价的。SP的弱耦合是以放弃类型安全为代价的。而
> OOP则保全了类型的安全,但却付出了强耦合的代价。
我举个例子,就拿SP版的collect说事:
对于Account上的ammount()而言,collect可以声明成。为了简单,我暂时不考虑Pred:
float collect(Account* a, float (Account::*m)()) {...}
为了复用,我们可以把它变成这样:
float collect(void* a, float (*m)()){..}
在C中,只能将所有类型归一化成void*,然后在内部处理类型问题。
但是这个函数只能用于一个类上的float ()类型的成员。现在,我要计算Department::EmployeeNum()来统计总人数。由于人
不会有半个,该成员函数返回int。于是,上述版本的collect无法使用。而GP则不但时a的类型得到解放,不再绑定于一个类型,而且使得那些签名
不再是一个,而是一簇签名。进一步为算法解耦。解耦的结果就是,算法的应用范围更广,灵活性更强。
pongba wrote:
> 上次的讨论 <http://groups.google.com/group/pongba/t/e553a21476ba2ebd>
> 真过瘾啊:-) 我把大家的意思总结了一下,接着讨论!
>
> 本文首先将耦合从本质上分为三个境界,然后阐述为什么C本质上趋向于更松耦
> 合的设计(没错,的确跟C语言本身有关),以及为什么C++的GP也能够带来同样
> <http://groups.google.com/group/pongba>
> >
--
blog: http://blog.csdn.net/jq0123
jinq...@gmail.com 写道:
> 还要看哪个使用简单.
>
>
On 9月20日, 上午10时33分, red...@gmail.com wrote:
> "方便" 必须有 context, 写一个200 行的一次性学生作业程序, 和写一个 10w
> 行, 需要持续维护的程序, "方便" 的含义并不相同.
>
> jinq0...@gmail.com 写道:
>
>
>
> > 还要看哪个使用简单.- 隐藏被引用文字 -
>
> - 显示引用的文字 -