首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将TForm作为参数传递给函数

将TForm作为参数传递给函数
EN

Stack Overflow用户
提问于 2020-10-12 15:48:27
回答 1查看 103关注 0票数 0

我有一份有几份表格的申请表。其中两个非常相似,它们具有VCL对象形式的特性(标签、图像等.)共同之处,我也是这样命名的。我希望在特定的类中有一个函数,它可以接受这两种形式中的一种作为参数,以便修改它们共有的参数。我找到的解决办法似乎行不通。

由于我的应用程序很大而且很复杂,所以我用一个小例子复制了这个问题。首先,下面是我的MainForm的一个例子:

以及一个subForm的例子(它们都是以类似的方式排列的)

我有一个额外的类,用来在subForms上填写编辑。该类的代码如下:

代码语言:javascript
复制
#pragma hdrstop

#include "master_class.h"
#include "sub_Form2.h"
#include "sub_Form3.h"
#include "sub_Form4.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)

Master::Master(void)
{

}

Master::~Master(void)
{

 }

 void Master::WriteToForm(TForm* Form)
{
TForm2* curForm = static_cast<TForm2*>(Form);

TForm3* self = dynamic_cast<TForm3*>(Form);
TForm2* self2 = dynamic_cast<TForm2*>(Form);

if (self != NULL && self2 == NULL) {
    TForm3* curForm = static_cast<TForm3*>(Form);
}

else if (self == NULL && self2 != NULL) {
    TForm2* curForm = static_cast<TForm2*>(Form);
}

curForm -> Edit1 -> Text = "blablabla_1";
curForm -> Edit2 -> Text = "blablabla_2";
}

在MainForm中,“填充Form2”按钮的代码如下:

代码语言:javascript
复制
Master1 -> WriteToForm(Form2);

其中Master1只是主类的一个对象。这对于Form2非常有用:

但是对于使用Form3填充的Master1 -> WriteToForm(Form3),下面是我得到的,与实际应用程序相同的pb:

所以,应该去编辑的东西,是错误的。我认为主要的pb是因为我没有创建每个标签,编辑等等。按同样的顺序。我这么做是为了模仿我的实际应用程序。为了验证这一点,我创建了第三个subForm,其中VCL对象是按照与第一个subForm相同的顺序创建的,这是可行的:

所以我怀疑这来自于最初的演员

代码语言:javascript
复制
TForm2* curForm = static_cast<TForm2*>(Form);

当我将Form3作为参数传递时,Form3在某种程度上被抛入Form2的“形状”中,这并不是按照相同的顺序定义的。也许可以通过直接修改DFM文件来纠正这一点,但对于我的主要应用程序来说,这并不是一种现实的方法。

我做这个初始的强制转换,否则我会得到一个编译错误,在第一行中不知道curForm

代码语言:javascript
复制
curForm -> Edit1 -> Text = "blablabla_1";

那么,是否有更好的方法将表单作为参数传递给WriteToForm函数?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-12 17:06:16

仅仅因为两种类型相似并不意味着它们是相关的。您的代码无法工作,因为您的两个表单类在任何方面都没有关联。你不能随随便便地把一个扔给另一个。

要解决这个问题,您有几种选择:

两个窗体类的

  1. 代码,例如:

代码语言:javascript
复制
void Master::WriteToForm(TForm* Form)
{
    TForm2* curForm2 = dynamic_cast<TForm2*>(Form);
    TForm3* curForm3 = dynamic_cast<TForm3*>(Form);

    if (curForm2)
    {
        curForm2->Edit1->Text = _D("blablabla_1");
        curForm2->Edit2->Text = _D("blablabla_2");
    }
    else if (curForm3)
    {
        curForm3->Edit1->Text = _D("blablabla_1");
        curForm3->Edit2->Text = _D("blablabla_2");
    }
}

或者:

代码语言:javascript
复制
void WriteToForm(TForm2* Form);
void WriteToForm(TForm3* Form);

...

void Master::WriteToForm(TForm2* Form)
{
    Form->Edit1->Text = _D("blablabla_1");
    Form->Edit2->Text = _D("blablabla_2");
}

void Master::WriteToForm(TForm3* Form)
{
    Form->Edit1->Text = _D("blablabla_1");
    Form->Edit2->Text = _D("blablabla_2");
}

Why can templates only be implemented in the header file?):

  1. 使您的函数使用模板(但是,请注意这一点:

代码语言:javascript
复制
template<typename T>
void WriteToForm(T* Form);

...

void Master::WriteToForm<T>(T* Form)
{
    Form->Edit1->Text = _D("blablabla_1");
    Form->Edit2->Text = _D("blablabla_2");
}

  1. 使两个表单类派生自一个公共基类或接口,例如:

代码语言:javascript
复制
class TBaseForm : public TForm
{
public:
    inline __fastcall TBaseForm(TComponent *Owner) : TForm(Owner) {}
    virtual void SetEdit1(const String &Text) = 0;
    virtual void SetEdit2(const String &Text) = 0;
};

...

class TForm2 : public TBaseForm
{
    ...
public:
    __fastcall TForm2(TComponent *Owner);
    ...
    void SetEdit1(const String &NewText);
    void SetEdit2(const String &NewText);
};

__fastcall TForm2::TForm2(TComponent *Owner)
    : TBaseForm(Owner)
{
    ...
}

void TForm2::SetEdit1(const String &NewText)
{
    Edit1->Text = NewText;
}

void TForm2::SetEdit2(const String &NewText)
{
    Edit2->Text = NewText;
}

...

repeat for TForm3...

...

void Master::WriteToForm(TBaseForm* Form)
{
    Form->SetEdit1(_D("blablabla_1"));
    Form->SetEdit2(_D("blablabla_2"));
}

或者:

代码语言:javascript
复制
__interface INTERFACE_UUID("{E900785E-0151-480F-A33A-1F1452A431D2}")
IMyIntf : public IInterface
{
public:
    virtual void SetEdit1(const String &Text) = 0;
    virtual void SetEdit2(const String &Text) = 0;
};

...

class TForm2 : public TForm, public IMyIntf
{
    ...
public:
    __fastcall TForm2(TComponent *Owner);
    ...
    void SetEdit1(const String &NewText);
    void SetEdit2(const String &NewText);
};

__fastcall TForm2::TForm2(TComponent *Owner)
    : TForm(Owner)
{
    ...
}

void TForm2::SetEdit1(const String &NewText)
{
    Edit1->Text = NewText;
}

void TForm2::SetEdit2(const String &NewText)
{
    Edit2->Text = NewText;
}

...

repeat for TForm3...

...

void Master::WriteToForm(IMyIntf* Intf)
{
    Intf->SetEdit1(_D("blablabla_1"));
    Intf->SetEdit2(_D("blablabla_2"));
}

  1. 使用RTTI访问字段,例如:

代码语言:javascript
复制
#include <System.Rtti.hpp>

void Master::WriteToForm(TForm* Form)
{
    TRttiContext Ctx;
    TRttiType *FormType = Ctx.GetType(Form->ClassType());

    TRttiField *Field = FormType->GetField(_D("Edit1"));
    if (Field)
    {
        TValue value = Field->GetValue(Form);
        if( (!value.Empty) && (value.IsObject()) )
        {
            TObject *Obj = value.AsObject();

            // Either: 

            static_cast<TEdit*>(Obj)->Text = _D("blablabla_1");

            // Or:

            TRttiProperty *Prop = Ctx.GetType(Obj->ClassType())->GetProperty(_D("Text"));
            if (Prop) Prop->SetValue(Obj, String(_D("blablabla_1")));
        }
    }

    Field = FormType->GetField(_D("Edit2"));
    if (Field)
    {
        TValue value = Field->GetValue(Form);
        if( (!value.Empty) && (value.IsObject()) )
        {
            TObject *Obj = value.AsObject();

            // Either: 

            static_cast<TEdit*>(Obj)->Text = _D("blablabla_2");

            // Or:

            TRttiProperty *Prop = Ctx.GetType(Obj->ClassType())->GetProperty(_D("Text"));
            if (Prop) Prop->SetValue(Obj, String(_D("blablabla_2")));
        }
    }
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64321081

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档