?不是有泛型 模板之类的吗?
进而你可以实现更复杂的逻辑,那个需要左对齐,哪个需要右对齐,哪个控件需要和其他的同时出现,哪个又和其它不能同时出现,哪个又包含了另外一些。
发挥你的想象力,使用一些类如 std::setw, std::left, std::right 的技巧,把界面的编写变成文本文件的输出一样简
单
On Apr 16, 10:30 am, LeeoNix <leeoni...@gmail.com> wrote:
On Apr 16, 12:14 pm, LeeoNix <leeoni...@gmail.com> wrote:
> 呵呵,我尝试做了一下修改,感觉还真不错哦。
> 其他地方的初始化也可以这么写,又不失去效率。
> 而且<<操作符重载可以写成全局的,不用写在类里面,让类接口感觉很清晰。''
>
> win.add_members() << btn << lbl << edt;
> win << btn << lbl << edt;
> 后一种感觉是不是有点异样?
> 我还是感觉前一种有add_members说明会更清晰一些。
>
> 不过我怕的一点就是像Hub Scott分析sprintf的问题的时候所说的,
> sprintf最大的优点就是用%d%s这些方便。
>
> 2009/4/16 rockeet <rock...@gmail.com>
助手类将访问接口分离出来,在需要提供多种不同接口或接口有较多变动时,是有好处的,但增加了助手类,就增加了开销,这点在c++上是不能不考虑的,而java和ruby一般不考虑这微乎其微的损失,所有的灵活性都是有代价的,权衡只能看应用了。
btw:讨论问题要就事论事,大家火气小一点,否则就和论坛一样了,即便说一些小白的话,一笑而过好了,态度认真是好的,但应对事不对人。
--
wing
wing9...@gmail.com
Hope is a good thing, maybe the best of things.
至于可以玩出什么花样, 就看需要了 ......
On 4月16日, 上午10时30分, LeeoNix <leeoni...@gmail.com> wrote:
On 4月16日, 上午10时30分, LeeoNix <leeoni...@gmail.com> wrote:
为什么C++要引入static_cast之类的转型操作符,原因之一就是像 (int*) pBuffer 这样的表达式基本上没办法用grep判断
出它是个强制类型转换,写不出一个刚好只匹配类型转换的正则表达式。
如果类型转换都用*_cast,那只要grep一下我就能知道代码里哪儿用了reinterpret_cast转换,便于迅速地检查有没有用错。
在我看来,重载operator()应仅限于和stl algorithm配合时使用,比如transform(),其他情况都用具名函数为宜。原因之
一是,我根本用grep找不到在哪儿用到了operator()。
例如Google Protocol Buffers的回调时class Closure,它的接口用的是virtual function Run
()而不是virtual operator()。
http://www.google.com/codesearch/p?hl=en#WTeibokF6gE/trunk/src/google/protobuf/stubs/common.h
On Apr 16, 10:47 am, qiaojie <qiao...@gmail.com> wrote:
> 看不出跟
> win.add_members(btn);
> win.add_members(lbl);
> win.add_members(edt);
> 有什么差别
>
> win.add_members() ( btn ) ( lbl ) ( edt )
> 这种写法实在是丑陋,初次使用的人还得去研究AddMemberHelper是怎么工作的,无端的增加使用者的脑力负担。在接口上玩弄技巧是设计上的大忌。
>
> 2009/4/16 LeeoNix <leeoni...@gmail.com>
个人感觉,如果是一些个人的,或者说小型的项目,这样的语法糖抽象的确是可以起到少敲代码、简洁直观的作用。
但假如是数万行、数十万甚至上百万行的大中型项目,里面可能包含了各个不同团队开发的库、模块的话,从维护角度,这样的"语言意外"用法还是少些为
妙。
这里的"语言意外"主要指的是过多地使用运算符重载。
因为在这样的项目里,每个开发人员读到的大部分code都不是他自己写的,有可能是其他人写的,也有可能是几年前离开团队的人写的。
所以,维护这样的代码,我宁愿看到100行老老实实的像
win.add_members(btn);
win.add_members(label);
...
这样的代码,而甚至不愿看到
win.add_members(btn)(label)(...);
或者(我认为更好一些的):
win << btn << label << ...;
因为前者虽然行数很多可能要写上百行,但都是机械性的,逻辑上非常简单。如果我要修改某个内容,search一下也不难。
对后者虽然代码数很少,但多了一层抽象逻辑,这意味着如果是debug跟踪到这段对我来说是新代码的情况的话,我还要找出这个运算符重载的定义,并且检
查这个抽象有没有问题。
而且数百万行的项目里不能指望所有代码的编写者都能沟通一致。可能在其它的库里,又会有这样的写法,于是在不同的小团队负责的不同模块里,我还可能分别
遇见:
networkStream < xxxData < yyyData << format.change(zzzFormat) <<
blablablabla....;
mainFramework += coolBtn += coolLabel += coolSubWindow -= toolBar;
当然上面还算小儿科,还有玩得更"专业"的团队写的:
dialog << (canvas = (OKButton("OK", Box(200, 300, 500, 700)) &=
pfnOnButtonOK &= OKNotificationFunction) && CancelButton("Cancel", Box
(200, 600, 500, 1000)) &= pfnOnButtonCancel)), text1(200, 300) % RGB
(255, 0, 0), text2(500, 200) * Mode(Text::Underline |
Text::TransparentBackground)
这里面用了各种操作符来"巧妙"地构建了一个对话框,包括创建各个控件,绑定相关的事件函数,设置控件格式。重载了包括"<<", "=",
"&=", ",", "%"...的操作符。
写的人是很爽,当年使用这一套机制的团队因为对这些东东熟练于心,用得也还算爽。但几年过去,作为新的维护者----可能是几年后的新人,或者是把这个模块
移植到另一个项目的人----看到这堆酷炫东东的时候,还要一个一个地方地去找这些符号的含义,复杂度不亚于新学习一套语法。这种情况下,至少我个人而言,
更宁愿阅读几十上百行的"愚蠢的"代码:
Text text1;
text.setPosition(200, 300);
text.setColor(255, 0, 0);
...
Box box(200, 300, 500, 700);
Button OKButton;
OKButton.setRect(box);
OKButton.addListener(pfnOnButtonOK);
OKButton.addListener(OKNotificationFunction);
...
好吧,虽然行数的确非常多,但形式上其实很整齐,都是机械重复,对于脑力上的理解,对Bug的定位、查找都很方便。单步调试的时候,后者是一行一行往下
走,打断点,观察都直观流畅,但对前者而言则是麻烦的事情。我也不需要去记不同模块、不同object可能会对"<<"有不同的重载这类容易引出混乱的
规则。甚至于像下面简单的例子:
window.addMember(button1);
很可能这是我跟踪到的某个从来没有打开过的源码文件中的某一行,但我可以信赖这是一个函数调用,而不用担心原作者重载了operator()然后背地里
做了什么我所不知道的东东于是保险起见还得查找window类的定义文件,然后做一个仔细search才可以确认。
像这样的语法糖抽象,其实节省的只是头一次编写时几分钟机械敲键盘的时间。但一个项目的进度瓶颈不在于这几分钟敲键盘的时间(如果是,只能说明你的项目
实在太简单了,不需要引入这么复杂的讨论来^_^)。等创建这套语法糖的开发v1.0的人们爽完了,在后面更长时间的维护、新版本创建期,这些东西带来
的将是噩梦:比如,新版本的开发由不同的新人来完成,或者,某个之后的新项目会引用的是不同团队编写的模块、库,然后不同的库都有各自一套的火星重
载、"仿函数潜规则",很明显,第一次编写代码省下来的机械几分钟完全无法弥补新时期去理解、维护、调试这些"语言之上的新语言"的机制的时间、脑力。
初看起来,几十上百行的setXXX, addXXX好像很重复很愚蠢,但正因为"愚蠢",才不至于成为理解上的困难。而且,这些"重复"是本质上的复
杂:你永远需要创建这么些不同的按钮,组件,定义不同的事件行为,这样的话,这些重复并不像是软件工程说的"避免代码重复"里的重复那样需要远避之。
当然,不能说绝对。像iostream那样的库也用了那样的重载。但有一个前提,你如果决定使用这套机制,你必须保证你的库的使用者(可能是整个企业的
人,甚至相关业界的人士)长期地统一坚持使用、熟悉这套东东,形成类似iostream那样雷打不动的标准,免去多次学习的负担。而且你一开始的设计必
须要足够正确,免得后面改了一个"%="操作符而千里之外的用户浑然不知。但如果你的库使用者来自外界,比如开源粉丝,他们愿不愿意学这一套那就不好说
了。比如可能开源界的另一人士又自己定义了一套火星重载库,于是大家都学不过来,转而使用老实的setButtonPos(...)库了。
因此,设计架构的时候,保持接口形式的简单一致是很重要的。最一致的东西是语言标准本身原生定义的像函数调用、内置操作符这样的东东。其实最朴素地使用
函数接口已经足够了。真正大的项目对C++这样有"扩展危险"的语言的使用是非常有节制的,比如限制运算符重载、限制template的使用等等。甚至
有当成"更好的C"来用的。这其间不无原因:大项目无一不需要长期的、多人的协作维护,各说各话是造不成通天塔的。
当然,如果你觉得你的设计只是用于学习C++,做做课程设计,只由不多于三个人维护(包括你的潜在代码观众),存活期不超过三年,那么以上的讨论可以作
废。毕竟自己搞自己的一套抽象,对于C++初学者而言还是很爽的体验,也应该鼓励----有多少人学C++的时候没有自己封过Array呢?:)
最后顺便说一下,其实你原来的需求不需要这样的流式重载也可以有很简洁明了的实现的:
1) 首先像这样的情况所有的Button, Label, EditBox实在是应该继承自一个统一的抽象接口,比如叫什么Control类。于是只
需要一个add_members(Control *pCtrl)
2) 然后剩下的代码就可以这样写:
Control *win_elements[] = { new Button, new Label, new EditBox, ...,
0 } // 空指针标记结尾,或者也可以记下数组的size
for (Control *pCtrl = &win_elements[0], *pCtrl, ++pCtrl)
{
win.add_members(pCtrl);
}
On Apr 16, 10:30 am, LeeoNix <leeoni...@gmail.com> wrote:
有些程序员可能会把自己写代码的机会当作试验田,试验各种他的新奇想法,这对公司是不负责任的,特别是当这个程序员还比较稚嫩或者品味不好的时候。而减
少这种情况的发生,则是技术经理的责任。
好的代码是看起来平平无奇,但是就是能很好的工作。说"返璞归真"是有点太高了,不过大概就是那个意思。
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
vec.push_back(5);
vec.push_back(6);
这样的代码,首先第一反应要考虑是不是设计上出问题了。我不认为增加运算符重载,或者其它方案这样的语法糖衣就能改进多少(相反,副作用可能更大)。
比如,在这个pushback的例子里,如果数据之间有内在逻辑的关联性的话,首先考虑能不能由程序生成这些数据。如果可以,初始化的时候for一下由
CPU生成当然是最简便的。
假如不能(或者代价太大),说明这些数据很可能(如果不是一定的话)是资源性质数据,而非引导程序流程的普通变量。这样一来,为什么还要把这么些数据硬
编码到代码段中,而不是分离开来?----比如说放到单独的数据资源段或者资源文件中然后由程序读入?要知道,资源数据硬编码到代码段中是设计上的大忌。应
当避免。
On 4月24日, 下午4时46分, LeeoNix <leeoni...@gmail.com> wrote:
> 比如开发游戏。UI就是那几个东西。根本就不需要复杂的。
>
> 哪怕有个公共的Creator或者Factory去生成一些列的UI也无可厚非,也符合工厂模式的结构。
>
> 设计也是分形式的,不是一概而论的。当一个需求限定在某个圈子里,已经不会再有过多扩展的时候,你的话是否还继续合理呢?
>
> 后面有个朋友也提到了boost库里面的make_list_inserter
>
> 就可以清晰明了的表达一系列的操作,用重载+=操作符和,操作符。
>
> 用vec += 1,2,3,4,5,6;
>
> 你看这种方便?
>
> vec.push_back(1);
> vec.push_back(2);
> vec.push_back(3);
> vec.push_back(4);
> vec.push_back(5);
> vec.push_back(6);
>
> 还是这样方便?
>
> 当我们大家都知道+=是个什么含义的时候,这样写是非常有意义的。
>
> 不是你所说的,我"宁愿"看多少多少行代码的那种。
>
> 我看了你写这么多,还是没怎么明白你说什么。
>
> 你是再说我写的例子代码里重载操作符的问题?还是AddMember的问题?
>
> 我后面的回复已经提到了,我改,我改还不行。
>
> 我承认我错了。我错了,大家就饶了我吧,例子代码也这样,我的标题都没人看了。
>
> 而我的标题是什么?Helper类而已,如果Helper类的设计有问题,请提出来。
>
> 我下次再也不敢写什么"花哨"的代码了。还有可能会出现的"不合理"的设计。
>
> 举例都这么麻烦,我实在受不了了。
>
> 2009/4/24 kusk <kuangsheng...@gmail.com>
> ...
>
> 阅读更多 >>- 隐藏被引用文字 -
>
> - 显示引用的文字 -
On Apr 24, 7:25 pm, "K.L." <xxxK.L....@gmail.com> wrote:
> 我不同意C++心智包袱说。boost::assign就是类似的东西,特定的情况下还是有用的。
哎..哎..哎....实在不应该参与到这种小白贴的讨论中....class Window};
{
public:
void add_members(const Button* value);
void add_members(const Label* value);
void add_members(const EditBox* value);从来没见过有这么傻X的接口设计。如果我有几十种控件,难道我要写几十个add_members函数?难道你的Button,Label,EditBox没有公共基类的?写一个void add_members(Control* value); 不就结了么?居然还加const修饰作茧自缚,哪天你的child对象里有一个parent变量,add_members的时候需要set_parent了怎么办呢?难道修改接口?要么内部const_cast一下?
虽然固然可以采用C/C++变长参数函数特性实现,但正如printf不如iostream(类型安全性、简洁性)一样,利用运算符的流式重载会更直观
且具有类型安全。
至于此类Helper的适用范围,依个人浅见,双目运算符其实相当于二元函数,但优势是复合调用时书写更简洁:a+b+c+d终归比add(add
(add(a, b), c), d)方便。所以对于可能要复合很多层的调用,即具有"若干数量不确定的不同类型的对象需要串行化输出(入)"语义的时
候都可以采用。
比如iostream可以认为是对不同对象的串行化IO;MFC的CArchive以及一个好像是用于网络数据传输的class(也是重载<<,>>)
亦类似;此例则是串行化输出到函数调用栈。
如果项目中大量用到和Lua交互的情况,这个抽象(自己实现抑或使用Boost)不失为一个比较通用的方案。对于经常会有这样需求的项目(群),统一作
为一个基本方案/库是很好的主意。
不过假若这类情况不够一般(比如所在的公司并非游戏公司也不是所有项目都与Lua挂接的话,或者就项目的代码规范干脆不允许运算符重载),"老朽"的土
法也并非没法解决。我个人还是倾向于使用如下老式Helper,把所有调用Lua函数的操作都封装成Helper函数(这里有一个期望,就是C++所调
用的Lua函数数量不应当太多,比如好几百个甚至上千个;如果太多,很可能不是一个好的设计),可能像这样:
void LuaState::mouse_wheel(Userdata *pSender, long x, long y) // 参
数瞎写的,没接触过Lua...
{
lua_pushuserdata(_state, this);
lua_pushnumber(_state, x);
lua_pushnumber(_state, y);
... // call mouse_wheel of Lua
}
这样一个基本的隔离就把Lua的调用封装起来了。坏处就是说这些Helper的实现本身还是一大堆的lua_pushnumber......不过个人认为其实
认为不是什么太大的问题。毕竟封装嘛,就是把脏的东东封装起来,统统打包到一个模块里就可以眼不见为净了。而除了封装者本人,不会有另外的人需要关心
Lua的函数如何调用、参数如何入栈的,甚至不知道有Lua的存在。万一哪一天完全不用Lua了,上层的东西一点也不用改:依然是最最平凡函数调用。而
如果用运算符重载,若是下面的实现哪天改成了用C,上面的运算符重载机制是不是还有必要保留(不留的话会理改接口,在大项目里面会牵连无数,留的话相当
于什么事没做会让后来看代码的人莫名其妙),也是一个问题。这也是坚持使用函数作为接口的好处。
> 2009/4/24 kusk <kuangsheng...@gmail.com>
> ...
>
> read more >>
void LuaState::mouse_wheel(Userdata *pSender, long x, long y) // 参
数瞎写的,没接触过Lua...
{
lua_pushuserdata(_state, this);
lua_pushnumber(_state, x);
lua_pushnumber(_state, y);
... // call mouse_wheel of Lua
}
在 09-4-24,qiaojie<qia...@gmail.com> 写道:
--
从我的移动设备发送
2009/4/25 莫华枫 <longsh...@gmail.com>:
> 几位别在争吵了,更不要作人身攻击。这不符合TL的规则。问题讨论到“我是怎么说的”“你是怎么看问题的”“谁谁谁小白”这种程度已经过了。你们的言论都有一些实在的内容,但却夹杂着这些无谓的言论,如果真的想在TL里学习知识,获得长进,请检要紧的说。
>
>
--
Any complex technology which doesn’t come with documentation must be the best
available.
作为看贴的我都觉得火大.
2009/4/24 LeeoNix <leeo...@gmail.com>:
--
Dan Quayle - "I love California, I practically grew up in
Phoenix." -
http://www.brainyquote.com/quotes/authors/d/dan_quayle.html
中途把例子中的重载()变成了push
似乎总算说明楼主是想要说设计成操作总是返回自身的helper类的好处
就是可以写成链式的
但是后边又举例lua中用重载"+="和","后的形式helper+=this,x,y
来代替
lua_State* L = luaL_newstate();
lua_pushuserdata(L, this);
lua_pushnumber(L, x);
lua_pushnumber(L, y);
那么,似乎又再说,设计一个有重载运算符,使得看上去是一种新语法的helper类的好处
再加上一上来一楼的例子
所有人都有理由理所当然的认为你是在说后一种helper类
于是理所当然的都集中在重载运算符来窗在新语法这个问题上了
实际上楼主应该去设计DSL而不是设计什么helper类
总算有点明白了,楼主是在考虑 用输入参数流 调用不定参数方法初始化的问题?
楼主用新式的方法解决了问题,就已经足够,大家应该随喜。至于说楼主你发起的讨论的中心好像吸引不到大家(如楼主说的总是出现偏离主题的人群,
which我相信是无意的,包括我自己在内^_^. ),我斗胆猜测,可能和C++社群近年返朴的趋势有关:开帖看到win.foo(btn1)
(xx)(yy)这样的设计对于抽象过敏型的人而言还是蛮震惊的;而且同一个抽象机制,对于一个例子可能是过于聪明,但另一些例子则不是。这也是为什么
我一直针对你的例子回复的原因:并非抓着细节把柄不放,而是说如果没有具体的例子,完全没有办法判断优劣,甚至于说有可能是不佳的设计才导致了过于聪明
的用法。楼主一开始如果举出压栈封装的例子,相信观众会好接受许多。大家出现偏题理解,想必大多无心,还望楼主原谅。
至于说一些情绪化的回帖,我也是坚决不赞成的,不管其技术立场、能力如何。也不断有朋友在提醒了(啊,我希望自己不是被"提醒"的其中一员,我可一直是
对事讨论的,虽然可能不是很合题意呵呵)。跟自认为强的人、自己敬佩的人探讨,保持情绪上的中立(甚至崇敬),完全不难。但不够,要做到跟自认为(仅仅
是自认为!)某些技术领域不如自己的人讨论的时候还要保持就事论事、对事不对人,才是专业的探讨问题的态度。出现谁也不服谁演化到人身攻击式的"讨
论",实在应该引起大家的注意,毕竟楼主是讨论发起人,不管技术立场如何,都应该尊重。
On Apr 25, 3:55 am, LeeoNix <leeoni...@gmail.com> wrote:
> >这里有一个期望,就是C++所调用的Lua函数数量不应当太多,比如好几百个甚至上千个;如果太多,很可能不是一个好的设计
>
> 回答你这个期望。没有好几百,类型我大概数了下,是63个。以后还可能比这个更多。
> 2009/4/25 kusk <kuangsheng...@gmail.com>
> ...
>
> read more >>
2009/4/25 qiaojie <qia...@gmail.com>:
--
H. L. Mencken - "It is even harder for the average ape to
believe that he has descended from man." -
http://www.brainyquote.com/quotes/authors/h/h_l_mencken.html
~~~ ~~~ 晕 楼主举的例子好像误导大众了
如果一个class确实需要有100个方法,我觉得应该尽量把方法分类写清楚,而不是把方法放到另外一个class去。比如CWnd,里面林林总总的方
法是很多,但也没有谁把里面的OnPaint方法就写到另外一个class去。
我不知道我们两个说的"helper"是不是同一个东西。另外,"helper"是一个有特定含义的专有名词吗(像interface、thread那
样)?
把一个class的member function写到另外一个class去,伴随着的多半是把member var从private声明为
protected,并且把另外那个class声明为friend。这只是形式上好看了一点,耦合性和复杂度并没有降低。逻辑既然还是老样子,该出的错
还是照样会出的。
On 4月25日, 下午9时41分, LeeoNix <leeoni...@gmail.com> wrote:
> 如果宿主有100个方法,但是版本不允许做大修改,方法太多又看着头疼,
>
> 可以独立出某一类类型的操作,为一个Helper类出现。
>
> Helper类就好像一个"分类"一样,降低宿主本身的接口数,添加类似接口的时候,就不要修改宿主了。
>
> 这是一个比较实用的重构方法,呵呵,倘若宿主本身不能做比较大的修改的话。
>
> 不过我还是感觉添加和读写的时候,使用helper类是很有趣的设计方法。
>
> 不至于让宿主本身的接口膨胀。
>
> 不过具体是否使用它,还得看具体的业务分析。
>
> 2009/4/25 chaoyan ma <chaoyan...@gmail.com>
至于那个Helper类,我觉得要么它是一个对象的wrapper,要么其函数大部分都是static的。这样可以把部分逻辑分开,虽然有好处,但是并
不明显。
真正值得争论的,应该是发现一个pattern,在工作中为了解决某一问题而研究出来的比较好的范式。拿出来讨论之后,多方推敲,反复修改,看客和自己
都有所收获,才是目的。
On 4月25日, 下午6时17分, qiaojie <qiao...@gmail.com> wrote:
> 这个楼主的逻辑是非常混乱的。既然他要谈helper类,那么当然要举例说明了,可是偏偏他就举了几个不好
> 的例子来,不但说明不了问题,反倒是让人感觉与其这样用helper还不如不用。于是有好心人给他指出例子
> 里的问题,结果他就莫名其妙的恼了,他说“你们凭无视我的论点,专挑我例子里的毛病?” 搞的大家都觉得
> 很莫名其妙。
> 楼主之所以这样逻辑混乱,只是因为他原本只是想显摆一下他最新研究出来的C++小技巧,他想听到的只是
> “写的太好啦”,”楼主英明"之类的溢美之词,可没想到上来就被泼了几盆冷水,其恼羞成怒自然也就容易理
> 解了。
>
> 2009/4/25 Doyle <doyle...@gmail.com>
class A
{
friend class AHelper;
protected:
int x;
}
class AHelper
{
int GetX(A* a) { return a->x; };
void SetX(A* a, int val) { a->x = val; };
}
上面这个例子是你想表达的意思吗?
On 4月25日, 下午11时59分, LeeoNix <leeoni...@gmail.com> wrote:
> 看我标题:
> [TL]{技术}在添加或者读写的时候,设计一个Helper类感觉很有趣。
> 我在标题里就写了四个字:添加、读写。
> 另外:Helper。
>
> 既然是助手类。其实就是把宿主的可以用的方法独立出来而已。
>
> 另外一种选择就是把这些写在某个类里面。可以选择助手,也可以选择直接写进类。
> 具体是否用Helper,要看具体的业务。不是一概而论的。
>
> 而我在标题里面明确提到了:"在添加或者读写的时候"。
> 倘若大家没有看到这一行字,我也就不想参与这个了。
> 我不知道是我标题写的不对,还是我表达的逻辑有问题。
> 如果我刚才说的那个属性读写的Helper的方法,
> 还不能让你明白的话,那可能就是我表达的问题。
> 可能以后我会再开一个帖子来说明。
> 也可能以后我在发表标题之后,要在里面用最大的字外加粗体去写清楚我的意思。
> 又是不是我没有明确表达一定要Add的类型,或者写get、set这样类型的函数给大家看,所出的问题?
> 感觉我写的这这么大一个标题已经变得没用了。
>
> 2009/4/25 Eric.Wang <wangshaoq...@gmail.com>
add_members这不是一个好接口,如果一定要,我更倾向于下面的方式:
有RTTI:
//return how many members are added
int add_members(CWnd* members, int member_count);
没有RTTI的话:
class MemberInfo
{
char type;
void* member;
}
//return how many members are added
int add_members(MemberInfo* members, int member_count);
On 4月26日, 上午12时08分, LeeoNix <leeoni...@gmail.com> wrote:
> 我在前面已经举了一个针对连续入栈的helper方式了。
>
> 如果你没看到的话,那我在写一个get,set函数的。
>
> 稍等。我的代码在内网机器上,不能复制,我只能比着,写个大概。
>
> 2009/4/26 Eric.Wang <wangshaoq...@gmail.com>