C++ 中大家使用什么样的事件模型?

204 views
Skip to first unread message

WL

unread,
Feb 20, 2006, 7:47:33 PM2/20/06
to 高性能网络编程邮件列表
很明显 C++ 里面没有一个很好的事件模型,除了 VC7
的统一事件模型之外,不知道大家都用的什么样的事件模型,都是自己写的吗?VC7的统一事件模型不知道性能、开销如何,文档太少了。

sunway

unread,
Feb 20, 2006, 8:55:18 PM2/20/06
to 高性能网络编程邮件列表
呵呵,我以前用DELPHI比较多,DELPHI的OnButtonClick之类的事件模型非常不错,我一直稀饭用。
而且实现一些很好的设计模式。
C++里可以自己实现一套类似的机制,利用对象函数指针配合模板。
就我所知 loki里有一套类似的机制。

sunway

unread,
Feb 20, 2006, 9:01:04 PM2/20/06
to 高性能网络编程邮件列表
一般的对象事件机制是这样(DELPHI中的机制。估计C++也一样)
typedef struct tagOBJEvent
{
class * pObj; //对象指针,作为函数第一个参数传递
funcptr * pFunc; // 函数地址
}COBJEVENT,*POBJEVENT;

调用的时候 编译器 COBJEVENT cEvent;
cEvent.pFunc(pObj,...) ; //参数列表

closeall

unread,
Feb 20, 2006, 9:02:03 PM2/20/06
to dev4s...@googlegroups.com
我初涉这个领域,不太理解你们所说的事件模型到底指得什么?就是说一件事件完成后在某个地方得到通知么?如果是这个意思的话,在windows的环境下有个事件内核对象。


sunway

unread,
Feb 20, 2006, 9:06:09 PM2/20/06
to 高性能网络编程邮件列表
因为发帖者提到的
C++,如果是内核事件的话这个是操作系统相关的。应该不是这种机制。
我估计是那种语言级 的事件机制。

Schidler zhong

unread,
Feb 20, 2006, 9:11:05 PM2/20/06
to dev4s...@googlegroups.com
to SunWay:
这好像用到了回调机制,不知是吗?

WL

unread,
Feb 20, 2006, 9:37:23 PM2/20/06
to 高性能网络编程邮件列表
我的意思就是:存在着A、B
2种对象,当A对象状态发生变化时候,B应该得到这样的通知。用设计模式的观点来说的话,这个就是“观察者模式”,也就是A是事件主体(Subject),B是事件观察者(Observer)。
具体语言上实现,一般就是实现为一个回调,B将自己注册到A中,当A某事件触发时候,会调用B的某个方法。用接口来描述就是下面这个:

//interface the all observer classes should implement
public interface IObserver
{
void Notify(object anObject);
}//IObserver

//interface that all observable classes should implement
public interface IObservable
{
void Register(IObserver anObserver);
void UnRegister(IObserver anObserver);
}//IObservable

下面就需要B 对象在 Notify 中,通过大量的Switch case
或者if else
来实现不同事件的不同处理。很显然当事件很多的时候,这个简直就是噩梦了。

.NET
里面没有使用上述的接口,而是使用了代理(Delegate)。这就更加简化了事件的处理。但是在
C++
中好像还没有什么好的办法。现在VC7中新增的统一事件模型,它新增了__hook,
__raise
等等几个不符合标准的关键字,的确能很直观的解决问题,但是不知道其效率、开销如何,不太敢使用,不知道哪位朋友有这方面的经验,或者有其他的解决办法。

sunway

unread,
Feb 20, 2006, 9:50:55 PM2/20/06
to 高性能网络编程邮件列表
恩,我猜你的想法就是我后来描述的

class A;
{
public:
COBJEVENT m_Event;
.....
}

使用的时候
A * pObject=new A;
//开始HOOK这个事件
pObject->m_Event=this->Func;
// unhook
pObject->m_Evnet=NULL;

//在A的代码里
A::Dothing()
if m_Event.pFunc!=NULL
//编译器做相关的代码
m_Event(this,.....);

这样使用最简单,
和目前的C#方式一样,不过C#是抄袭DELPHI的方式比注册方式还要简单,而且语法要
好看的多.

用摸版的实现办法可以看游戏编程jincui

luo licun

unread,
Feb 20, 2006, 9:58:49 PM2/20/06
to dev4s...@googlegroups.com
hi,
  同感,觉的delphi的事件很好用,不过说白了就是一个函数指针。WINDOWS一些api有回调函数,好象也是用这个东西。

 
2006/2/21, sunway <sunh...@gmail.com>:

WL

unread,
Feb 20, 2006, 10:01:46 PM2/20/06
to 高性能网络编程邮件列表
//开始HOOK这个事件
pObject->m_Event=this->Func;

中这里面 this->Func
怕是需要静态函数吧,直接调用成员函数估计会有一点难度。

sunway

unread,
Feb 20, 2006, 10:09:01 PM2/20/06
to 高性能网络编程邮件列表
直接调用成员函数是可以的,因为可以使用C++的成员函数指针,

下面就是例子
typedef void ( CEVENTPTR::* CObjectFuncPtr )(int nCount)

这样就可以了,我后面的一些代码是编译器实现的

if m_Event.pFunc!=NULL
//编译器做相关的代码
m_Event(this,.....);

sharon

unread,
Feb 20, 2006, 10:10:07 PM2/20/06
to dev4s...@googlegroups.com
Hi all,
关于事件处理模型,怎么没人提到ACE的Reactor呢?我们现在用的就是它。
 

sunway

unread,
Feb 20, 2006, 10:13:06 PM2/20/06
to 高性能网络编程邮件列表
Reactor是虚基类接口。确实也是回调,
但是感觉和本文讨论的问题有一些差别

sunway

unread,
Feb 20, 2006, 10:16:52 PM2/20/06
to 高性能网络编程邮件列表
不完全是函数指针,是一个结构体

typedef struct tagOBJEvent
{
class * pObj;
//对象指针,作为函数第一个参数传递
funcptr * pFunc; // 函数地址
}COBJEVENT,*POBJEVENT;

里面包含了 this
指针。和普通的函数指针还是有一些差别。

sunway

unread,
Feb 20, 2006, 10:18:29 PM2/20/06
to 高性能网络编程邮件列表
成员函数指针 (转帖)

在C++程序中,很多函数是成员函数,即这些函数是某个类中的一部分。你不可以像一个普通的函数指针那样指向一个成员函数,正确的做法应该是,你必须使用一个成员函数指针。一个成员函数的指针指向类中的一个成员函数,并和以前有相同的参数,声明如下:

float (SomeClass::*my_memfunc_ptr)(int, char *);

//对于使用const关键字修饰的成员函数,声明如下:

float (SomeClass::*my_const_memfunc_ptr)(int, char *) const;

注意使用了特殊的运算符(::*),而“SomeClass”是声明中的一部分。成员函数指针有一个可怕的限制:它们只能指向一个特定的类中的成员函数。对每一种参数的组合,需要有不同的成员函数指针类型,而且对每种使用const修饰的函数和不同类中的函数,也要有不同的函数指针类型。在MSVC中,对下面这四种调用方式都有一种不同的调用类型:__cdecl,
__stdcall, __fastcall, 和
__thiscall。(__thiscall是缺省的方式,有趣的是,在任何官方文档中从没有对__thiscall关键字的详细描述,但是它经常在错误信息中出现。如果你显式地使用它,你会看到“它被保留作为以后使用(it
is reserved for future
use)”的错误提示。)如果你使用了成员函数指针,你最好使用typedef以防止混淆。

将函数指针指向型如float SomeClass::some_member_func(int, char
*)的函数,你可以这样写:

my_memfunc_ptr = &SomeClass::some_member_func;

很多编译器(比如MSVC)会让你去掉“&”,而其他一些编译器(比如GNU
G++)则需要添加“&”,所以在手写程序的时候我建议把它添上。若要调用成员函数指针,你需要先建立SomeClass的一个实例,并使用特殊操作符“->*”,这个操作符的优先级较低,你需要将其适当地放入圆括号内。

SomeClass *x = new SomeClass;

(x->*my_memfunc_ptr)(6, "Another Arbitrary Parameter");

//如果类在栈上,你也可以使用“.*”运算符。

SomeClass y;

(y.*my_memfunc_ptr)(15, "Different parameters this time");

不要怪我使用如此奇怪的语法——看起来C++的设计者对标点符号有着由衷的感情!C++相对于C增加了三种特殊运算符来支持成员指针。“::*”用于指针的声明,而“->*”和“.*”用来调用指针指向的函数。这样看起来对一个语言模糊而又很少使用的部分的过分关注是多余的。(你当然可以重载“->*”这些运算符,但这不是本文所要涉及的范围。)

一个成员函数指针可以被设置成0,并可以使用“==”和“!=”比较运算符,但只能限定在同一个类中的成员函数的指针之间进行这样的比较。任何成员函数指针都可以和0做比较以判断它是否为空。与函数指针不同,不等运算符(<,
>, <=, >=)对成员函数指针是不可用的。

成员函数指针的怪异之处

成员函数指针有时表现得很奇怪。首先,你不可以用一个成员函数指针指向一个静态成员函数,你必须使用普通的函数指针才行(在这里“成员函数指针”会产生误解,它实际上应该是“非静态成员函数指针”才对)。其次,当使用类的继承时,会出现一些比较奇怪的情况。比如,下面的代码在MSVC下会编译成功(注意代码注释):

#include “stdio.h”

class SomeClass {

public:

virtual void some_member_func(int x, char *p) {

printf("In SomeClass"); };

};

class DerivedClass : public SomeClass {

public:

// 如果你把下一行的注释销掉,带有 line
(*)的那一行会出现错误

// virtual void some_member_func(int x, char *p) { printf("In
DerivedClass"); };

};

int main() {

//声明SomeClass的成员函数指针

typedef void (SomeClass::*SomeClassMFP)(int, char *);

SomeClassMFP my_memfunc_ptr;

my_memfunc_ptr = &DerivedClass::some_member_func; // ---- line (*)

return 0;

}

奇怪的是,&DerivedClass::some_member_func是一个SomeClass类的成员函数指针,而不是DerivedClass类的成员函数指针!(一些编译器稍微有些不同:比如,对于Digital
Mars
C++,在上面的例子中,&DerivedClass::some_member_func会被认为没有定义。)但是,如果在DerivedClass类中重写(override)了some_member_func函数,代码就无法通过编译,因为现在的&DerivedClass::some_member_func已成为DerivedClass类中的成员函数指针!

成员函数指针之间的类型转换是一个讨论起来非常模糊的话题。在C++的标准化的过程中,在涉及继承的类的成员函数指针时,对于将成员函数指针转化为基类的成员函数指针还是转化为子类成员函数指针的问题和是否可以将一个类的成员函数指针转化为另一个不相关的类的成员函数指针的问题,人们曾有过很激烈的争论。然而不幸的是,在标准委员会做出决定之前,不同的编译器生产商已经根据自己对这些问题的不同的回答实现了自己的编译器。根据标准(第5.2.10/9节),你可以使用reinterpret_cast在一个成员函数指针中保存一个与本来的类不相关的类的成员函数。有关成员函数指针转换的问题的最终结果也没有确定下来。你现在所能做的还是像以前那样——将成员函数指针转化为本类的成员函数的指针。在文章的后面我会继续讨论这个问题,因为这正是各个编译器对这样一个标准没有达成共识的一个话题。

在一些编译器中,在基类和子类的成员函数指针之间的转换时常有怪事发生。当涉及到多重继承时,使用reinterpret_cast将子类转换成基类时,对某一特定编译器来说有可能通过编译,而也有可能通不过编译,这取决于在子类的基类列表中的基类的顺序!下面就是一个例子:

class Derived: public Base1, public Base2 // 情况 (a)

class Derived2: public Base2, public Base1 // 情况 (b)

typedef void (Derived::* Derived_mfp)();

typedef void (Derived2::* Derived2_mfp)();

typedef void (Base1::* Base1mfp) ();

typedef void (Base2::* Base2mfp) ();

Derived_mfp x;

对于情况(a),static_cast<Base1mfp>(x)是合法的,而static_cast<Base2mfp>(x)则是错误的。然而情况(b)却与之相反。你只可以安全地将子类的成员函数指针转化为第一个基类的成员函数指针!如果你要实验一下,MSVC会发出C4407号警告,而Digital
Mars
C++会出现编译错误。如果用reinterpret_cast代替static_cast,这两个编译器都会发生错误,但是两种编译器对此有着不同的原因。但是一些编译器对此细节置之不理,大家可要小心了!

标准C++中另一条有趣的规则是:你可以在类定义之前声明它的成员函数指针。这对一些编译器会有一些无法预料的副作用。我待会讨论这个问题,现在你只要知道要尽可能得避免这种情况就是了。

需要值得注意的是,就像成员函数指针,标准C++中同样提供了成员数据指针(member
data
pointer)。它们具有相同的操作符,而且有一些实现原则也是相同的。它们用在stl::stable_sort的一些实现方案中,而对此很多其他的应用我就不再提及了。

成员函数指针的使用

现在你可能会觉得成员函数指针是有些奇异。但它可以用来做什么呢?对此我在网上做了非常广泛的调查。最后我总结出使用成员函数指针的两点原因:

* 用来做例子给
C++初学者看,帮助它们学习语法;或者

* 为了实现“委托(
delegate)”!

成员函数指针在STL和Boost库的单行函数适配器(one-line
function
adaptor)中的使用是微不足道的,而且允许你将成员函数和标准算法混合使用。但是它们最重要的应用是在不同类型的应用程序框架中,比如它们形成了MFC消息系统的核心。

当你使用MFC的消息映射宏(比如ON_COMMAND)时,你会组装一个包含消息ID和成员函数指针(型如:CCmdTarget::*成员函数指针)的序列。这是MFC类必须继承CCmdTarget才可以处理消息的原因之一。但是,各种不同的消息处理函数具有不同的参数列表(比如OnDraw处理函数的第一个参数的类型为CDC
*),所以序列中必须包含各种不同类型的成员函数指针。MFC是怎样做到这一点的呢?MFC利用了一个可怕的编译器漏洞(hack),它将所有可能出现的成员函数指针放到一个庞大的联合(union)中,从而避免了通常需要进行的C++类型匹配检查。(看一下afximpl.h和cmdtarg.cpp中名为MessageMapFunctions的union,你就会发现这一恐怖的事实。)因为MFC有如此重要的一部分代码,所以事实是,所有的编译器都为这个漏洞开了绿灯。(但是,在后面我们会看到,如果一些类用到了多重继承,这个漏洞在MSVC中就不会起作用,这正是在使用MFC时只能必须使用单一继承的原因。)

在boost::function中有类似的漏洞(但不是太严重)。看起来如果你想做任何有关成员函数指针的比较有趣的事,你就必须做好与这个语言的漏洞进行挑战的准备。要是你想否定C++的成员函数指针设计有缺陷的观点,看来是很难的。

在写这篇文章中,我有一点需要指明:“允许成员函数指针之间进行转换(cast),而不允许在转换完成后调用其中的函数”,把这个规则纳入C++的标准中是可笑的。首先,很多流行的编译器对这种转换不支持(所以,转换是标准要求的,但不是可移植的)。其次,所有的编译器,如果转换成功,调用转换后的成员函数指针时仍然可以实现你预期的功能:那编译器就没有所谓的“undefined
behavior(未定义的行为)”这类错误出现的必要了(调用(Invocation)是可行的,但这不是标准!)。第三,允许转换而不允许调用是完全没有用处的,只有转换和调用都可行,才能方便而有效地实现委托,从而使这种语言受益。

为了让你确信这一具有争议的论断,考虑一下在一个文件中只有下面的一段代码,这段代码是合法的:

class SomeClass;

typedef void (SomeClass::* SomeClassFunction)(void);

void Invoke(SomeClass *pClass, SomeClassFunction funcptr) {

(pClass->*funcptr)(); };

注意到编译器必须生成汇编代码来调用成员函数指针,其实编译器对SomeClass类一无所知。显然,除非链接器进行了一些极端精细的优化措施,否则代码会忽视类的实际定义而能够正确地运行。而这造成的直接后果是,你可以“安全地”调用从完全不同的其他类中转换过来的成员函数指针。

为解释我的断言的另一半——转换并不能按照标准所说的方式进行,我需要在细节上讨论编译器是怎样实现成员函数指针的。我同时会解释为什么使用成员函数指针的规则具有如此严格的限制。获得详细论述成员函数指针的文档不是太容易,并且大家对错误的言论已经习以为常了,所以,我仔细检查了一系列编译器生成的汇编代码…

Message has been deleted

WL

unread,
Feb 20, 2006, 10:32:16 PM2/20/06
to 高性能网络编程邮件列表
如果需要多个观察者呢,还需要一个成员函数指针容器吧

sharon

unread,
Feb 20, 2006, 11:01:34 PM2/20/06
to dev4s...@googlegroups.com
Reactor不是一个虚基类接口,事件处理器ACE_Event_Handler才是。Reactor一般是以单件的形式在程序里被使用。用户需要从Event_Handler派生出自己的子类,向Reactor注册;Reactor收到事件或者信号时,会调用该子类的相应方法。
假设Reactor是A对象,Event_Handler是B对象,我觉得Reactor模式与这里讨论的问题不一样的地方在于:
事件不是A对象所发生的,而是B对象本来要获取的,只是统一在A对象中去获取了。
不过总体说来,我觉得Reactor模式其实是解决了楼主想要解决的问题啊,不知道是不是我理解错了,:$

 
On 2/21/06, sunway <sunh...@gmail.com> wrote:

sunway

unread,
Feb 20, 2006, 11:42:06 PM2/20/06
to 高性能网络编程邮件列表
恩,我刚才大致看了下ACE的东西,我记错了,Reactor不是虚基类。
对于这个问题loki库提供了一个实现。大家可以找来看看。他支持=操
作去设置回调的

sunway

unread,
Feb 20, 2006, 11:43:45 PM2/20/06
to 高性能网络编程邮件列表
这个就是多播(C#中的做法),当然要list或者vector只类的容器了,C#是支持多播的。
这个只是实现的细节,看需求来决定是否使用多播。

WL

unread,
Feb 21, 2006, 12:40:49 AM2/21/06
to 高性能网络编程邮件列表
其实我就是想要一种使用起来,简洁高效的类似.NET中
delegate 的咚咚!

sunway

unread,
Feb 21, 2006, 12:45:41 AM2/21/06
to 高性能网络编程邮件列表
用对象函数指针自己实现一个也是很容易的。

leowu2000

unread,
Feb 21, 2006, 12:49:31 AM2/21/06
to dev4s...@googlegroups.com
我觉得大家聊天的话还是使用im比较好.
邮件的内容嘛,尽量自己想全了再回复,不然看着感觉是一堆的垃圾邮件.
谢谢.

sunway 写道:
> 用对象函数指针自己实现一个也是很容易的。
>
>
>

closeall

unread,
Feb 21, 2006, 12:56:51 AM2/21/06
to dev4s...@googlegroups.com
其实我个人这种方式很好,有点像bbs的感觉,但是他又是一种新的交流方式。当然口味难调。各有优缺点。至于像垃圾邮件,我到不这么认为,google这一点做得很好

2006/2/21, leowu2000 <leow...@gmail.com>:

sunway

unread,
Feb 21, 2006, 1:00:44 AM2/21/06
to 高性能网络编程邮件列表
随意一点好,而且大家一般白天都在工作,偶尔看一下Group,看到有新的想法回一下,
要什么都想全了,还要讨论干吗?

Donald

unread,
Feb 21, 2006, 1:18:58 AM2/21/06
to dev4s...@googlegroups.com
ACE中的reactor和practor都是事件模型,还有ACK
似乎用ACE开发网游的不是很多啊,为什么呢?

2006/2/21, sunway <sunh...@gmail.com>:


> 随意一点好,而且大家一般白天都在工作,偶尔看一下Group,看到有新的想法回一下,
> 要什么都想全了,还要讨论干吗?
>
>
>


--
Donald

Donald

unread,
Feb 21, 2006, 1:20:14 AM2/21/06
to dev4s...@googlegroups.com
一个事件模型也是比较容易实现的
主要是回调点的处理不同而产生了各种不同的事件模型


在 06-2-21,Donald<flyi...@gmail.com> 写道:


--
Donald

sunway

unread,
Feb 21, 2006, 1:25:08 AM2/21/06
to 高性能网络编程邮件列表
主要是回调点的处理不同而产生了各种不同的事件模型
?
不明白
现在用ACE开发游戏的就我知道的有几家,但是都是
小公司,没有技术实力做低层框架。
同时我看过一些ACE的书。感觉各种基础类比较丰富
但是稍微麻烦了一些。而且BUG也不少。
我们公司有项目组据说用过,后来放弃了,原因是麻
烦。

sharon

unread,
Feb 21, 2006, 1:36:36 AM2/21/06
to dev4s...@googlegroups.com
我们公司是做通信的,ACE我们用了一年了,开始用的时候好象问题比较多,后来发现问题其实都是我们自己没用好引起的,暂时还没发现ACE有什么BUG啊,呵呵。看来我们的水平比较次,:P

On 2/21/06, sunway <sunh...@gmail.com> wrote:

Donald

unread,
Feb 21, 2006, 1:39:26 AM2/21/06
to dev4s...@googlegroups.com
我不知道同各位理解的事件是否一样
我接触的事件模型都用在GUI和通讯框架中
事件模型无外乎事件的通知方式,以便能够回调自定义的事件处理代码
所以,各种回调方式的不同,就产生了不同的事件模型
比如
MFC的callback
Swing、MINA、Cindy的Listener
ACE的ACK、Proactor、Reactor
还有OSGI的White Board方式
甚至*nix上的signal
都是不同的事件回调点产生了不同的事件模型,WDYT?

我个人觉得ACE已经做的很不错了
麻烦我倒没觉得,可能是早在使用ACE之前就已经研究过很多网络框架的原因吧
基本上跟POSA2里面描述的没啥出入
不知道自己做底层框架做出来都是什么架构呢?
我很好奇

BUG不少?比如说呢?
老实说,ACE我现在也只是看,还没机会具体使用,有经验的不妨说一说啊

2006/2/21, sunway <sunh...@gmail.com>:


--
Donald

sunway

unread,
Feb 21, 2006, 1:41:56 AM2/21/06
to 高性能网络编程邮件列表
我有个同事专心研究ACE一年多把,用ACE也做过一些东西,他说(去年年初)ACE的BUG不少
服务器端程序测试下来性能一般。后来他就不用ACE了。

Donald

unread,
Feb 21, 2006, 1:45:36 AM2/21/06
to dev4s...@googlegroups.com
:)
有机会还是要请你那位同事出来布布道啊
2006/2/21, sunway <sunh...@gmail.com>:

> 我有个同事专心研究ACE一年多把,用ACE也做过一些东西,他说(去年年初)ACE的BUG不少
> 服务器端程序测试下来性能一般。后来他就不用ACE了。
>
>
>


--
Donald

sunway

unread,
Feb 21, 2006, 1:48:32 AM2/21/06
to 高性能网络编程邮件列表
一般的架构是指MMORPG的TCP/UDP组件。还包含内存管理,线程池等其他组件。
一般对于MMO
服务器端来说,基本上没有跨平台的可能。所以一般都是针对某
个平台进行优化,LINUX下EPOLL,win下是IOCP、其他重叠I/O。所以这种情况
下ACE基本上没什么用。就我说知道的,网易,腾讯,盛大
现在的大部分应用
都没有使用ACE。其他行业我就知道华为应该是使用过ACE的,因为我看过他们
内部出来的ACE教程。

Donald

unread,
Feb 21, 2006, 2:21:11 AM2/21/06
to dev4s...@googlegroups.com
用ACE可能主要还是为了跨平台吧
至少我想用它的目的是为了这个

2006/2/21, sunway <sunh...@gmail.com>:


--
Donald

Roger Chen

unread,
Feb 21, 2006, 2:33:28 AM2/21/06
to dev4s...@googlegroups.com
To sunway:

你们用什么工具测试服务器端性能?标准的工具还是自己写的?

--
Roger Chen <che...@gmail.com>

sunway

unread,
Feb 21, 2006, 2:44:12 AM2/21/06
to 高性能网络编程邮件列表
机器人程序测试,看CPU占用率,最简单的办法。

sunbi...@gmail.com

unread,
Feb 26, 2006, 3:55:45 AM2/26/06
to 高性能网络编程邮件列表
总结几点ACE的缺点,请大家拍板:
1. 听说ACE的效率不是非常高(道听途说,不是很肯定).
现在很多网游还都是用纯c写的,应该是处于效率方面的考虑吧.
2.
ACE为了实现跨平台,基本上把所有的api都封装了个遍,学习曲线比较陡峭.
3. 出了bug很难调试.

Hu Yi

unread,
Feb 26, 2006, 5:18:08 AM2/26/06
to dev4s...@googlegroups.com
〉〉1. 听说ACE的效率不是非常高(道听途说,不是很肯定).
〉〉现在很多网游还都是用纯c写的,应该是处于效率方面的考虑吧.
ACE作者自称是效率非常高的,和直接用c相差无几,这也是ACE追求的目标,应用得当,可能比自己手写代码还快,毕竟在封装易用性的同时,也封装了很多专家知识进去。
我没有对比过,也无法单从效率上来说明两种做法的好坏,毕竟现在单纯追求效率的软件太少了。
〉〉2.
〉〉ACE为了实现跨平台,基本上把所有的api都封装了个遍,学习曲线比较陡峭.
ACE封装API,易用性并没有降低,只不过是把原来的API移植到了一个新的命名空间下,原来怎么用,现在还怎么用 ,而且现在是跨平台的。
〉〉3. 出了bug很难调试.
ACE中大量使用了IoC,这类程序难调试是必然的了,但是几乎所有框架级的东西,都有这个毛病,牵扯上多线程,就更复杂了。

Donald

unread,
Feb 26, 2006, 7:40:40 AM2/26/06
to dev4s...@googlegroups.com
关于ACE效率不好的说法倒是第一次听说
从我看到的ACE框架中,处处都体现着效率第一的设计思想

在 06-2-26,sunbi...@gmail.com<sunbi...@gmail.com> 写道:


--
Donald
My Blog:http://flyingbug.blogjava.net

大宝(sodme)

unread,
Feb 26, 2006, 11:36:07 AM2/26/06
to dev4s...@googlegroups.com
hi all:
我只听说过由于ACE框架太大,暂时没法把握而没采用它的,还没有听说过由于ACE存在无法解决的重大BUG而拒绝采用它的。


--
Best regards
大宝(sodme)
msn : sod...@hotmail.com
Email : sodm...@gmail.com

sunbi...@gmail.com

unread,
Feb 27, 2006, 8:46:24 AM2/27/06
to 高性能网络编程邮件列表
hehe,我的意思不是说ACE有bug,而是我自己写的程序有bug。
偶现在正处于ACE学习的初级阶段,还没有用它搭过像样的应用,ACE的源码更是没有信心和时间去研究,继续学习。。。。。

alvi...@gmail.com

unread,
Feb 27, 2006, 11:22:47 AM2/27/06