如何将子项的方法作为参数传递给父项中的函数

how to pass method of child as parameter to function in parent

本文关键字:参数传递 函数 方法      更新时间:2023-10-16

在以下非常简短的类中,我想在基中定义一个方法(ProcessLines),该方法将迭代一组数据库记录,将每个记录作为参数传递给仅在子类中定义的函数。 显然,Base 是一个虚拟类,永远不会自行实例化。

Class Base {
 public:
  typedef ProcLineFunc( Long *Line );
  void ProcessLines( ProcLineFunc pf);
}
Class Child{
  void DoWork( Long *Line) { //do something}
}

我不确定如何实现这一点。如果我在子项中重新声明 ProcessLines 并只调用父方法,则会收到与在创建子项的代码中调用 ProcessLines 相同的错误消息。

Child c(//something);
c.ProcessLines(c.DoWork);

给我一个编译器消息:

[BCC32 错误] 主.cpp(67): E2034 无法将"布尔值 (* (_closure )(长 *))(长)">转换为"整数"()(长 *)"
完整解析器上下文
主.cpp(56):类 Add2Chan
main.cpp(78): 决定实例化: bool Add2Chan::P rocessByLines()
--- 重置解析器上下文以进行实例化...
主.cpp(67): 解析: bool Add2Chan::P rocessByLines()

我对 c++ 相当陌生,E2034 错误消息吓坏了我。

请帮忙。我使用了一个typedef,这样我就可以在我的子类中多次调用ProcessLines,在我去的时候传递不同的函数。

通常你会用一个受保护的纯虚函数来做这种事情:

class Base {
  public:
    ProcessLines() {
        //Logic to process lines here, obviously psuedo-code
        while(moreLines) {
            ProcessLine(line);
        }
    }
  protected:
    virtual void ProcessLine(const Line& line) = 0;
}
class Child : public Base {
  protected:
    void ProcessLine(const Line& line) { //Logic to process the line for this type }
};
class DifferentChild : public Base {
  protected:
    void ProcessLine(const Line& line) { //Logic to process the line for DifferentChild }
};

我认为这就是你要找的东西。在我看来,您似乎正在尝试以一种奇怪的方式实现多态性,但这是在C++中实现多态性的正常方法。

不要使用指向函数的指针,而是使用指向对象的指针。接受你的函数将被调用DoWork而不是其他任何限制,并且每个类中只能有一个这样的函数。这不是一个糟糕的限制。在类(称为接口)中声明(纯虚拟)函数,并从中派生类(据说它们实现接口)。

struct DoingWork
{
    virtual void DoWork(long *Line) = 0; // does some work on a list
};
struct DoingGreatWork: DoingWork
{
    virtual void DoWork(long *Line) {printf("Great workn");}
};
struct DoingSlightWork: DoingWork
{
    virtual void DoWork(long *Line) {printf("Slight workn");}
};

使用此示例:

class Base {
  public:
    void ProcessLines(DoingWork& object) {
        //Logic to process lines here
        while(moreLines) {
            object.DoWork(line);
        }
    }
};
class Whatever // no need to derive from Base
{
    void DoStuff()
    {
        Base object;
        object.ProcessLines(DoingGreatWork());
        object.ProcessLines(DoingSlightWork());
    }
}

如果工作对象必须有权访问调用对象,请像这样初始化它们:

class Whatever // no need to derive from Base
{
    struct DoingElaborateWork: DoingWork
    {
        Whatever& caller;
        DoingElaborateWork(Whatever& caller): caller(caller) {}
        virtual void DoWork(long *Line)
        {
            printf("Doing work requested by %sn", caller.name());
        }
    };
    void DoStuff()
    {
        Base object;
        object.ProcessLines(DoingElaborateWork(*this));
    }
    const char* name() {return "Whatever";}
}

附言他们说"在 C++03 中函数是二等公民",因为你不能用函数做你可以对对象做的事(比如我提供的这个解决方案)。我听说在 C++11 中功能得到了很大的改进,但我不确定细节。

由于您在 C++Builder 中执行此操作,因此您可以利用其__closure扩展来执行您所要求的操作(VCL 的某些部分对自己的回调完全这样做):

class Base
{ 
public: 
    virtual ~Base() {}
    typedef void (__closure *ProcLineFunc)( Long *Line ); 
    void ProcessLines( ProcLineFunc pf); 
}; 
class Child : public Base
{ 
public:
    void DoWork( Long *Line) { //do something} 
}; 
Child c(...); 
c.ProcessLines(c.DoWork);