gpt4 book ai didi

c++ - TBitBtn 和 TButton 继承链发生了什么变化?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:26:07 26 4
gpt4 key购买 nike

我最近开始将我的 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 年它失败了。查看用于从 TButton 派生的 2007 TBitBtn 的继承链。因此,TButton 类共享任何按钮控件(即 OnClick)上预期发生的事件。因此,我能够将我的 TBitBtn 类视为 TButton

2007继承链:

  • TBitBtn : TButton

2009传承链:

  • TBitBtn : TCustomButton
  • TButton : TCustomButton

在 2009 年,TButtonTBitButton 都派生自 TCustomButton,我想如果按钮之类的属性在那里保存的话,这会很好。如果是这种情况,我可以只更改代码来处理 TCustomButton。不幸的是,TCustomButton 不支持OnClick 之类的东西。因此,我不能再将 TBitBtn 视为 TButton。这两个类现在都有自己独立的按钮,如属性(即它们都有自己的 OnClick 事件声明)。我的意思是,至少提供一个接口(interface)或类似的东西,比如 TButtonTBitBtn 实现的 IButton

似乎这些看似无害的更改可能会造成不必要的破坏。这看起来很奇怪,我想知道是否有人知道为什么 CodeGear(或与此相关的任何 Framework 作者)会做这种事情?

更重要的是,鉴于这种支离 splinter 的继承,是否有优雅解决方案将 TBitBtn 视为TButton

最佳答案

TButton 和 TBitBtn 仍然继续共享一个共同的 OnClick 事件,因为它是在 TControl 级别一直向下实现的,并且一直如此。 TButton 只是将 protected TControl::OnClick 事件提升为已发布,然后 TBitBtn 将继承该事件。

在 D2009 中,TCustomButton 与其他 TCustom... 类一样,不会将 protected 成员从基类提升为已发布。 TButton 和 TBitBtn 将 protected TControl::OnClick 事件提升为单独发布。但事件本身仍然存在于 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,它们有自己的 OnClick 事件,即:

#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
}
};

关于c++ - TBitBtn 和 TButton 继承链发生了什么变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/946316/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com