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

时间:2012-06-10 19:49:40

标签: c++ c++builder

在以下极为简短的类中,我想在基础中定义一个方法(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错误] main.cpp(67):E2034无法将'bool(*(_ enclosure)(long *))(long )'>转换为'int()(long * )“
   完整的解析器上下文
     main.cpp(56):class Add2Chan
     main.cpp(78):实例化的决定:bool Add2Chan :: ProcessByLines()
     ---重置解析器上下文以进行实例化...
     main.cpp(67):解析:bool Add2Chan :: ProcessByLines()

我对c ++很新,E2034的错误信息吓坏了我。

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

3 个答案:

答案 0 :(得分:4)

通常情况下,您会使用受保护的纯虚函数执行此类操作:

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 ++中实现它的常规方法。

答案 1 :(得分:1)

不使用指向函数的指针,而是使用指向对象的指针。接受你的函数将被称为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 work\n");}
};

struct DoingSlightWork: DoingWork
{
    virtual void DoWork(long *Line) {printf("Slight work\n");}
};

使用此示例:

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 %s\n", caller.name());
        }
    };

    void DoStuff()
    {
        Base object;
        object.ProcessLines(DoingElaborateWork(*this));
    }

    const char* name() {return "Whatever";}
}

P.S。他们说“在C ++ 03中functions are second-class citizens”,因为你不能用你可以用对象做的函数(比如我提供的这个解决方案)。我听说在C ++ 11中功能有很大的改进,但我不确定细节。

答案 2 :(得分:0)

由于您是在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);