TBitBtn 和 TButton 继承链发生了什么?
我最近开始将我的 RAD Studio 2007 项目升级到 RAD Studio 2009。我注意到的一件事是,看似简单的代码突然无法编译。
示例代码:
class CButtonPopupMenu
{
// Snip
public:
void Init( TButton* SrcButton )
{
SrcButton->OnClick = OnButtonClick;
}
private:
void __fastcall OnButtonClick( TObject* Sender )
{
// Do some button click stuff
}
};
// Snip
TButton button = new TButton( this );
TBitBtn bitBtn = new TBitBtn( this );
CButtonPopupMenu popupButton = new CButtonPopupMenu( button );
CButtonPopupMenu popupBitBtn = new CButtonPopupMenu( bitBtn );
这一切都用于编译,但在 2009 年它失败了。 查看 2007 年用于派生自 TButton
的 TBitBtn
的继承链。 因此,任何按钮控件上预期的事件(即 OnClick)都由 TButton
类共享。 因此,我能够将我的 TBitBtn
类视为 TButton
。
2007 继承链:
- TBitBtn : TButton
2009 继承链:
- TBitBtn : TCustomButton
- TButton : TCustomButton
在 2009 年,TButton 和 TBitButton strong> 派生自 TCustomButton,我想如果按钮之类的属性保存在那里就可以了。 如果是这种情况,我只需更改代码来处理 TCustomButton 即可。 不幸的是,TCustomButton 不包含诸如 OnClick 之类的东西。 因此,我不能再像对待TButton那样对待TBitBtn。 这两个类现在都有自己独立的按钮类属性(即它们都声明了自己的 OnClick 事件)。 我的意思是,至少提供一个接口或其他东西,例如 TButton 和 TBitBtn 都实现的 IButton 。
似乎这些看似无害的变化可能会造成不必要的破坏。 这看起来很奇怪,我想知道是否有人知道为什么 CodeGear(或任何与此相关的框架作者)会做这种类型的事情?
更重要的是,考虑到这种碎片化的继承,是否存在一种优雅的解决方案来将TBitBtn视为TButton?
I've recently began to upgrade my RAD Studio 2007 project to RAD Studio 2009. One thing I noticed is when seemingly simple code all of a sudden failed to compile.
Example Code:
class CButtonPopupMenu
{
// Snip
public:
void Init( TButton* SrcButton )
{
SrcButton->OnClick = OnButtonClick;
}
private:
void __fastcall OnButtonClick( TObject* Sender )
{
// Do some button click stuff
}
};
// Snip
TButton button = new TButton( this );
TBitBtn bitBtn = new TBitBtn( this );
CButtonPopupMenu popupButton = new CButtonPopupMenu( button );
CButtonPopupMenu popupBitBtn = new CButtonPopupMenu( bitBtn );
This all use to compile, but with 2009 it's failing. Looking at the inheritance chain for 2007 TBitBtn
used to derive from TButton
. Therefore, events that are expected on any button control (i.e. OnClick) were shared by the TButton
class. Therefore, I was able to treat my TBitBtn
class as a TButton
.
2007 inheritance chain:
- TBitBtn : TButton
2009 inheritance chain:
- TBitBtn : TCustomButton
- TButton : TCustomButton
In 2009, both TButton and TBitButton derive from TCustomButton, which would be fine I suppose if the button like attributes were held there. If this were the case, I could just change the code to deal with a TCustomButton instead. Unfortunately, TCustomButton does not hold things like OnClick. Therefore, I can no longer treat a TBitBtn like a TButton. Both of these classes, now have their own separate button like attributes (i.e. they both have their own OnClick event declared). I mean, at least provide an interface or something, like IButton that both TButton and TBitBtn implement.
It seems that these types of seemingly innocent changes are the ones that can wreak unnecessary havoc. This seems odd and am wondering if anyone knows why CodeGear (or any Framework author for that matter) would do this type of thing?
More importantly, given this fragmented inheritance, is there and elegant solution to treat a TBitBtn like a TButton?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
TButton 和 TBitBtn 仍然继续共享一个共同的 OnClick 事件,因为它从一开始就在 TControl 级别上一直实现,而且一直如此。 TButton 只是将受保护的 TControl::OnClick 事件提升为已发布,然后 TBitBtn 将继承该事件。
在 D2009 中,TCustomButton 与其他 TCustom... 类一样,不会将受保护的成员从基类提升为已发布。 TButton 和 TBitBtn 促进受保护的 TControl::OnClick 事件单独发布。 但事件本身仍然存在于TControl级别。
由于它在 TControl 级别受到保护,因此您可以使用访问器类来访问它,即:
或者,对于任何通用 TControl 指针:
更优雅的解决方案是使用 RTTI,这也允许您处理其他类型的对象,例如 TSpeedButton,它们有自己的 OnClick 事件,即:
甚至:
TButton and TBitBtn do still continue to share a common OnClick event, as it is implemented all the way down at the TControl level to begin with, and always has been. TButton was merely promoting the protected TControl::OnClick event to published, which TBitBtn would then inherit.
In D2009, TCustomButton, like other TCustom... classes, does not promote protected members from base classes to published. TButton and TBitBtn promote the protected TControl::OnClick event to published individually. But the event itself still exists at the TControl level.
Since it is protected at the TControl level, you can use an accessor class to reach it, ie:
Or, for any general TControl pointer:
A more elegant solution would be to use RTTI instead, which would also allow you to handle other types of objects, such as TSpeedButton, which have their own OnClick event, ie:
Or even:
如果这是 Delphi,我建议使用带有 is 和 as 运算符的 TCustomButton 类:
顺便说一句, C++ 已经太久远了
,VCL 有时不包括要提供的操作按钮、菜单等与调用代码之间的单一接口?
If this was Delphi, I would suggest the TCustomButton class with the is and as operators:
C++ is simply too long ago
btw, didn't the VCL sometime include Actions to provide a single interface between buttons, menus, etc and invoked code?