发生了什么事TBitBtn和TButton继承链?
-
09-09-2019 - |
题
我最近开始升级我的RAD室2007年的项目,以RAD室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年 TBitBtn
使用来自 TButton
.因此,活动是预期在任何按钮的控制(即击)是共用的 TButton
类。因此,我能够享我的 TBitBtn
类作为一个 TButton
.
2007年继承链:
- TBitBtn:TButton
2009年继承链:
- TBitBtn:TCustomButton
- TButton:TCustomButton
2009年,这两个 TButton 和 TBitButton 来自 TCustomButton, 这将是美好的,我想如果按钮就像属性被关押在那里。如果是这种情况,我可能只是变革的代码处理 TCustomButton 代替。不幸的是, TCustomButton 不抱东西喜欢 击.因此,我再也无法治疗 TBitBtn 像一个 TButton.这两个课程,现在有自己的独立的按钮就像属性(即他们两个都有自己的击事件的声明).我的意思是,至少提供一个接口,或者东西,像 IButton 这两个 TButton 和 TBitBtn 实施。
看来,这些类型的看似无辜的变化是那些可以造成不必要的破坏。这似乎很奇怪,我不知道如果有人知道为什么codegear出现(或者任何框架,提交人对于这个问题)会做这种类型的事情吗?
更重要的是,鉴于这种零散的继承,是那里 优雅 解决方案来治疗 TBitBtn 像一个 TButton?
解决方案
TButton和TBitBtn做的仍然继续享有共同击事件,因为它是实现所有的方式在TControl级开始,一直都是。TButton是仅仅促进保护TControl::击事件发表,其TBitBtn会然后继承。
在D2009,TCustomButton,像其他TCustom...类,并不能促进保护成员基类出版。TButton和TBitBtn促进保护TControl::击事件发布的独立。但事件本身仍然存在的TControl的水平。
因为它是保护在TControl水平,可以使用一个类访问,以达到它的,即:
class TCustomButtonAccess
{
public:
__property OnClick;
};
class CButtonPopupMenu
{
// Snip
public:
void Init( TCustomButton* SrcButton )
{
((TCustomButtonAccess*)SrcButton)->OnClick = OnButtonClick;
}
private:
void __fastcall OnButtonClick( TObject* Sender )
{
// Do some button click stuff
}
};
或者,对于任何一般TControl指针:
class TControlAccess
{
public:
__property OnClick;
};
class CControlPopupMenu
{
// Snip
public:
void Init( TControl* SrcControl )
{
((TControlAccess*)SrcControl)->OnClick = OnControlClick;
}
private:
void __fastcall OnControlClick( TObject* Sender )
{
// Do some click stuff
}
};
一个更优雅的解决方案将使用RTTI相反,这样也让你来处理其他类型的对象,例如TSpeedButton,它们有自己的击事件,即:
#include <TypInfo.hpp>
class TControlAccess
{
public:
__property OnClick;
};
class CControlPopupMenu
{
// Snip
public:
void Init( TControl* SrcControl )
{
TMethod m;
m.Code = &OnControlClick;
m.Data = this;
SetMethodProp(SrcControl, "OnClick", m);
}
private:
void __fastcall OnControlClick( TObject* Sender )
{
// Do some click stuff
}
};
或甚至:
#include <TypInfo.hpp>
class CObjectPopupMenu
{
// Snip
public:
void Init( TObject* SrcObject )
{
TMethod m;
m.Code = &OnObjectClick;
m.Data = this;
SetMethodProp(SrcObject, "OnClick", m);
}
private:
void __fastcall OnObjectClick( TObject* Sender )
{
// Do some click stuff
}
};
其他提示
如果这是德尔菲,我会建议的TCustomButton类的 是 和 作为 经营者:
if (SrcButton is TButton) then
(SrcButton as TButton).OnClick := OnButtonClick
else if (SrcButton is TBitButton)
(SrcButton as TBitButton).OnClick := OnButtonClick;
C++只是很久以前
顺便说一句,不VCL的某个时候包括行动提供一个单一的接口之间的按钮,菜单等并调用的密码?