在C++ Builder中,是否需要调用Synchronize()以及如何调用Synchronize()的问题

3

我的环境:

操作系统 - Windows7 Pro(32位)

集成开发环境 - RadStudio XE2 Update4

我对Synchronize()函数感到困惑。

Synchronize()函数在线程程序中使用。关于在C+ builder中使用Synchronize()的示例如下(可以在这里看到)。

//   Important: Methods and properties of objects in VCL can only be
//   used in a method called using Synchronize, for example:
//
//      Synchronize(&UpdateCaption);
//
//   where UpdateCaption could look like:
//
//      void __fastcall TMyThreadClass::UpdateCaption()
//      {
//        Form1->Caption = "Updated in a thread";
//      }

我有些困惑的是,在一些旧版本的C++ builder(比如bcb6)中,使用了Synchronize()方法。

// Synchronize(UpdateCaption);

函数名前不需要加上"&";

在Delphi代码中,与此处相同,函数名前也不需要加上"&"。

// Synchronize(UpdateCaption);  

那么,在C++ Builder中使用Synchronize()的正确方法是什么呢?

// Synchronize(UpdateCaption);  

或者

// Synchronize(&UpdateCaption);  

我在实际代码中尝试了两种方法,但它们的工作方式似乎是一致的。 UpdateCaption和&UpdateCaption是否都返回函数地址?


2
在标准C++中,UpdateCaption&UpdateCaption是非法的。这是C++Builder的扩展,对于一个成员函数,&UpdateCaption会被评估为一个__closure,它是指向对象和该对象上的成员函数组合的指针。(C++11将闭包添加到语言中;然而,C++Builder早于此很长时间,因此他们不得不为其添加自己的扩展)。显然,还有一个特性,即在重载决议中,UpdateCaption隐式转换为&UpdateCaption,尽管它本身不会这样做!(例如,UpdateCaption;会产生错误)。 - M.M
@MattMcNabb:感谢您的评论。所以这是C++ Builder的扩展,而不是标准的C++。 - sevenOfNine
是的 - 标准C++(C++11之前)没有闭包;您可以获取地址的唯一函数是非成员函数。 - M.M
@MattMcNabb:那不是真的。标准C++多年来一直有成员函数指针,因此您可以获取成员函数的地址。只是使用非常有限。Synchronize()(和事件)特别依赖于Borland的__closure扩展,它比MFP更灵活。MFP仅适用于特定类。闭包则不是这样,这使得将不同的类分配给相同的指向成员变量的指针成为可能。 - Remy Lebeau
@RemyLebeau 我的意思是在标准C++中 &FunctionName 是不起作用的。要获取一个成员函数指针,你必须写成 &ClassName::FunctionName 的形式。 - M.M
@MattMcNabb:在这方面我同意。 - Remy Lebeau
1个回答

4
所以,使用Synchronize()的正确方法是什么?
// Synchronize(UpdateCaption);
还是
// Synchronize(&UpdateCaption);
这两种方法都可以,但是&更受欢迎。
UpdateCaption和&UpdateCaption都返回函数地址吗?
是的。如果您引用一个没有为参数列表指定括号的函数/方法,则假定该函数/方法的地址。&只是使其更加明确。

对于成员函数 f;,会出现错误,但是 &f; 不会,所以情况并不是那么简单。似乎只有在特定的上下文中(至少其中之一是作为函数参数时),才会将 f 转换为 &f - M.M
虽然在这个例子中不清楚UpdateCaption是成员函数还是非成员函数(如果它不是成员函数,则可以将其设置为静态函数,因为它实际上并没有使用this)。 - M.M
@MattMcNabb:Synchronize()需要一个成员方法(或在现代版本中使用匿名过程,但在C++中使用起来很困难)。Synchronize(UpdateCaption)Synchronize(&UpdateCaption)之间的区别取决于编译版本。正如OP所说,在BCB6中两者都可以工作,但在后来的版本中已经更改,因此用户应始终仅使用Synchronize(&UpdateCaption)。在代码中分配事件处理程序时也适用相同的规则,例如:Comp->OnEvent = Handler;Comp->OnEvent = &Handler; - Remy Lebeau
非常感谢您的回复,Remy Lebeau和Matt McNabb。所以我应该使用Synchronize(&UpdateCaption)。@RemyLebeau:还要感谢您注意到分配事件处理程序。我没有意识到。 - sevenOfNine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接