damn MI (cont'd)

ajoo 2002-06-12 03:03:17
Sigh. do I have to write a book to clarify such a simple versioning problem?

Let's say, you use inheritance like
class A: public B, public RTTI<A, B>{
};
ok, good, users have getTypeName, getSuperType functions.

then you give this lib to your coworkers.

three months later, you realized that "hey, wouldn't it be a good idea to add getNamespace() into the RTTI?" so, you work and work and work, finally RTTI has another virtual function
virtual const char* getNamespace();

But, you did not know what a guy, already used this function in his class B.
So actually if he says
class B: A, RTTI<A, B>{......};
he will not get the expected behavior for getNamespace() because he used this function for some other purpose.

In that case, I would suggest you to summon a meeting with all the developers and say "hey, does any one of you used the name getNamespace() in your class?"
...全文
127 35 打赏 收藏 转发到动态 举报
写回复
用AI写文章
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
cloudwu 2002-06-15
  • 打赏
  • 举报
回复
这两年是做 MMORPG
可能下来要做 SLG, 或者一个模拟建设的游戏.

一直都是做底层的东西, 图形显示, 资源调度, UI engine 等等.
R&D 的工作比较多, 同事来用我的东西.
接下来可能就改做策划了, 写程序将成业余的爱好 :)
ajoo 2002-06-14
  • 打赏
  • 举报
回复
I thought we were talking about is whether mi is 100% replacable by aggregation, or whether you have to use mi sometimes (as for whether aggregation or mi is better, there're a lot of analysis out there, and I've restated my points for several times)

1. you raised a rtti example to show that "we sometimes have to use rtti".
then I gave an aggregation version of it.

2. you said:
"如果我要求把
getTypeName()
getSuperType()
都可以直接调用, 而不用令人困扰的getTypeInfo().getTypeName() 这样的方式调用呢?
那是不是要在宏里再加上一些 inline 函数
如果有更多的要求, 是不是要再加呢, 最后你的宏会越来越庞大"

does that mean you may want to add new methods in your rtti class?

and now you are saying:
"如果不是后面的程序员想重新定义一个 RTTI的实现, 重名的可能性微小的"

ok. what should I say?
I showed the coupling problem in subclassing; I gave an aggregation version for your example. You've known that mi may also have performance overhead, not superior to aggregation for even performance reason.

now, could you please tell me the reason why you just like to use mi?
straight-forward looking?
saves some keystrokes?


"我反对的是, 抵制 MI 本身".
That's perfectly fine. :)
but we are discussing the pros and cons now, right? blindly announcing "mi should be prohibited" is not objective, but what about blindly claiming "mi should not be prohibited"?
We are technical people, Don't be too emotional.

upcasting, downcasting 时指针的物理变化同样不是 MI 独有的.
SI does not have that.
ajoo 2002-06-14
  • 打赏
  • 举报
回复
What kind of game do you develop?
3D? RPG?
I was doing game programming for some time too.
cloudwu 2002-06-14
  • 打赏
  • 举报
回复
inheritance 不过是 "is-a" 吧
至少还有 "implement-from"
要不怎么还区分 public inheritance 和 private inheritance 呢 :)

我可能到不了设计上多高的高度, 讨论这些也只是玩玩.
毕竟项目里还有许多 asm 的代码, 那些是没有丝毫 OO 的.
有的只是怎么排列代码, 可以加快 1,2 个时钟周期.

ajoo 2002-06-14
  • 打赏
  • 举报
回复
Sigh. OO beginners like to use inheritance extensively and think hard about "whether A is B? Can I inherit A from B?".
and sometimes they may come up with stuff like 取父亲的一部分,母亲的一部分.抛弃掉了另外一部分.
That makes the system like a beggar with millions of patches. :)

"Wu Ren Zi Di" ya! those stupid OO books.throw them away!

if you really understand "programming against interface", all those "complex" problem can be much easier solved using interface, interface, interface, nothing else.

cloudwu 2002-06-14
  • 打赏
  • 举报
回复
yeah rtti 是很简单, 我也举不出什么复杂的例子.
现在自己写过的最大的东西, 也不过 5 万行的程序.
我只是相信以后会碰到更复杂的问题.

那个父亲母亲的句子, 我是看来的, 随口一说, 经不起这样推敲的.
而且生物的繁殖, 是取父亲的一部分,母亲的一部分.
抛弃掉了另外一部分(这在 C++ 里可是没有的 :)
但是有共有的绝大部分. 我觉得更像菱形的继承一点.
你不是你的父亲, 也不是你的母亲, 而是他们生命的延续.
这和 C++ 当然不同, 不过能否看到一些相同点呢?
ajoo 2002-06-14
  • 打赏
  • 举报
回复
"为什么有 MI,因为你有你的父亲和你的母亲"
totally nonsense!
inheritance means a "is-a" relationship.
Am I my father? Am I my mother? Faint!
ajoo 2002-06-14
  • 打赏
  • 举报
回复
"所以没有感觉到 MI 的非常必要性, 或许是面对的问题的复杂度还不够"
can you give an example which is complex enough? the rtti is apparently too easy.

thought the reason those design pattern people and many OO experts recommend aggregation is because aggregation is better for complex problem domain and system. Maybe my understanding is wrong? or they are trying to sell something inappropriate?

Your SI example is right. I'm wrong.
another sin for inheritance. :)

cloudwu 2002-06-14
  • 打赏
  • 举报
回复
上面前两句话, 写的匆忙, 语句没写清楚.

class A { int a; };
class B : public A { int b; virtual void f() {} };
class C : public B { int c; virtual void f() {} };

C *c=new C;
A *a=c;
看看 a 和 c , 数值是相等的吗?



cloudwu 2002-06-14
  • 打赏
  • 举报
回复
基类不是无虚函数的时候,
继承它, 加了一个虚函数.

这样类指针转换也会有编译器的修正.

我曾经不喜欢 MI, 现在喜欢是因为我正在学习和研究它.
而且我相信问题到达一定的复杂度, 解决的手段也会相应提高复杂度,
ASM/C/C++ 的语言设计哲学有一个相同点, 就是贴近计算机本身的模型.
这点是一脉相承的. 从这个角度看, 如果不是问题的复杂度提高到一定的层次, 就不需要有更高级和复杂语言, ASM 进化到 C 是如此,
C 进化到 C++ 也如此. 给 C++ 增加新特性, 比如 MI 也是如此.

至于 java, C#, 我认为偏离"计算机本身的模型", 所以不在这讨论.

所以没有感觉到 MI 的非常必要性, 或许是面对的问题的复杂度还不够.
而世界本身的构建, 更像 MI 一些. 引用一句有名的话 "为什么有 MI,
因为你有你的父亲和你的母亲"

cloudwu 2002-06-13
  • 打赏
  • 举报
回复
我的习惯是虚函数都做成 private 的, 外部不可直接调用. 只能重新改写
好象那个 do_move()
而对外的接口不是虚的, 它只是调用那个虚函数的实现. 好象那个 move()

我是说搞清楚,正确的使用是复杂的
但是实现出来给人用是简单的.

比如用 MI 来构建库, 用的人没搞清楚前就不要再在基础上
乱用 MI 再把东西搞的混乱.

iostream 不就是 MI 实现的吗? 用的人很多嘛.
cloudwu 2002-06-13
  • 打赏
  • 举报
回复
关于 MI 的问题, 已经不想再争论了. 我觉得不可能再得到什么有意义的结论 :) 如果纯粹是为了说服对方, 好象更没有什么意义.

我重来没认为 MI 是简单的东西, 可以不用的时候也不会故意去用.
我反对的是, 抵制 MI 本身. 它的存在并不是哪位老兄一时高兴
加到 C++ 标准里的. 它也不是为初学者准备的玩具.

而后面说到的那个函数名问题. 并不仅仅是 MI 特有的.
而 getTypeName 这种名字, 如果不是后面的程序员想重新定义一个 RTTI
的实现, 重名的可能性微小的很. 而 getRTTIInfo 这样的函数同样有
可能重名. 这并不成为 MI 使用于否的障碍. private 虚函数,
如果害怕重名的话, 完全可以写成 _rtti_xxxx().

ps. upcasting, downcasting 时指针的物理变化同样不是 MI 独有的.
就算你不用 MI, 同样也能碰到. 这点在早年我从 C 转到 C++
时, 一样给过我困惑. 接受一个超出自己已经融会贯通了的东西之上,
带来诸多复杂度的玩意, 本身就需要时间, 实践机会, 或对或错,
都还搀杂了许多私人的感情. 并非短期能改变的.

ajoo 2002-06-13
  • 打赏
  • 举报
回复
move(), do_move(), I'm confused by u. but whichever is virtual, it'll cause the same problem as I mentioned.
people always think they know how "goto" is implemented; They always think "goto" can make things simpler; They always think they are experienced enough to use "goto".
But, those who claimed that they had to use "goto" are normally beginners. :)

But anyway, do you think MI is "simple" or "complex"?
you said it's "simple" first, but now it becomes "complex"?
you said aggregation is "complex", but now you are suggesting beginners to use it? while experienced programmer like you just go for "simple" mi. Does that sound fair? :)
ajoo 2002-06-13
  • 打赏
  • 举报
回复
move(), do_move(), I'm confused by u. but whichever is virtual, it'll cause the same problem as I mentioned.
people always think they know how "goto" is implemented; They always think "goto" can make things simpler; They always think they are experienced enough to use "goto".
But, those who claimed that they had to use "goto" are normally beginners. :)

But anyway, do you think MI is "simple" or "complex"?
you said it's "simple" first, but now it becomes "complex"?
you said aggregation is "complex", but now you are suggesting beginners to use it? while experienced programmer like you just go for "simple" mi. Does that sound fair? :)
cloudwu 2002-06-13
  • 打赏
  • 举报
回复
move() 不是虚的, 正如成员函数指针最好不要指虚函数一样,
我通常都是用这个方法来解决问题的.

我不主要 beginner 滥用(甚至是使用) MI. 毕竟它相对复杂的多.
要理解了 virtual inheritance,
知道了 MI 的准确时间和空间效率, 清楚其内存分布,
并知道编译器是如何实现的. 然后还要在一些实验性代码中
实践一段时间, 才可以带到项目里去用.

否则, beginner 还是用聚合的方式来解决问题的好.
cloudwu 2002-06-13
  • 打赏
  • 举报
回复
move() 不是 virtual 的
我不主张 beginner 滥用(甚至使用) MI, 毕竟它相对复杂的多.

至少要在真正了解了 virtual inheritance
知道他们准确的时间和空间开销, 内存的分布是怎样的, 编译器是怎样
实现的, 对于MI的复杂度和可能带来问题有了深入的了解,
并在用实验性的程序实践了一段时间后, 才可以带入项目里去用.

否则的话, beginner 最好的选择还是用聚合. 那样可以减低设计复杂度
而且非常小的效率差别是可以忽略的.

ajoo 2002-06-13
  • 打赏
  • 举报
回复
man, do you understand the versioning problem so far? it seems to you that you are still wondering about that.

iostream? do you subclass from it? atl is also using mi.
but, you have to be extremely careful and know what you're doing. (seems you claim you know what you're doing for mi, but, why you are not aware of the versioning problem?)

ajoo 2002-06-13
  • 打赏
  • 举报
回复
your virtual function is private. but what if the subclass had a non-virtual function with the same name? before you add your private virtual function?

does the subclass author have to change his code to say MyClass::the_func()? he used to just write the_func().


blame him "you should not name it like that"?


ajoo 2002-06-13
  • 打赏
  • 举报
回复
when I say mi's bad, I'm from the lib author's view. the callers just call the functions. they won't care it's mi or aggregation normally.
my points are:
1. inheritance has design problem (still disagree?)
2. mi does not have performance advantage compared to aggregation
3. mi makes it even harder to maintain your system
4. when caller uses upcasting, downcasting on your mi, he may have trouble because compiler is moving the point up and down, and the caller may not be aware of that.
what mi gives you:
1. seems more straightforward at the beginning when you design it, requres less thinking. But it makes the system more complex.
2. may save a few keystrokes for the lib author and caller.

see, the advantages are rather trivial compared to the disadvantages.
ajoo 2002-06-13
  • 打赏
  • 举报
回复
your move() is also virtual, right? if you expect subclass to override it, you'll have the problem I mentioned. nothing can be solved by the template-method.

MI 是直观且高效的选择?
more 直观 for beginners. 高效? hard to say.
聚合方法首先有效率的下降. compared to MI? hard to say
而且有时候会不直观. harder for beginners of course.
加载更多回复(15)

69,370

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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