C++ C++;双重分派示例

C++ C++;双重分派示例,c++,visitor-pattern,double-dispatch,C++,Visitor Pattern,Double Dispatch,我把这段代码作为双重分派的一个例子,但我并不真正理解代码的一部分。创建“抽象类”打印机,为什么需要添加: virtual void print(PDFDoc *d)=0; virtual void print(DocDoc *d)=0; 据我所知,在运行时p.print(docA)会将我发送到myPrinter的虚拟无效打印(Document*d),然后d->printMe(this)会将我发送到PDFDoc的printMe,然后它会在运行时调用我的打印机的虚拟无效打印(PDFDoc*d)

我把这段代码作为双重分派的一个例子,但我并不真正理解代码的一部分。创建“抽象类”打印机,为什么需要添加:

virtual void print(PDFDoc *d)=0;
virtual void print(DocDoc *d)=0; 
据我所知,在运行时
p.print(docA)
会将我发送到myPrinter的
虚拟无效打印(Document*d)
,然后
d->printMe(this)
会将我发送到PDFDoc的printMe,然后它会在运行时调用我的打印机的
虚拟无效打印(PDFDoc*d)

那么为什么要定义

virtual void print(PDFDoc *d)=0;
virtual void print(DocDoc *d)=0; 
抽象类是否需要

class Document{
public:
      //this is the accept function
      virtual void printMe(Printer *p)=0;
};

    class Printer{
    public:
    virtual void print(Document *d)=0;

     //the visitors
     virtual void print(PDFDoc *d)=0;
     virtual void print(DocDoc *d)=0;
     };

 class PDFDoc : public virtual Document{
 public:
     virtual void printMe(Printer *p){
         std::cout << "PDFDoc accepting a print call" << std::endl;
         p->print(this);
     }
 };

class DocDoc : public virtual Document{
public:
    virtual void printMe(Printer *p){
        std::cout << "DocDoc accepting a print call" << std::endl;
        p->print(this);
    }
};


class MyPrinter : public virtual Printer{
public:
    virtual void print(Document *d){
        std::cout << "dispatching function <print> called" << std::endl;
        d->printMe(this);
    }
    virtual void print(PDFDoc *d){
        std::cout << "printing a PDF doc" << std::endl;
    }
    virtual void print(DocDoc *d){
        std::cout << "printing a Doc doc" << std::endl;
    }
};

int main(){
    MyPrinter p;
    Document *docA = new PDFDoc();
    Document *docB = new DocDoc(); 
    p.print(docA);
    p.print(docB);
    delete docA;
    delete docB;
    return 0;
}
类文档{
公众:
//这是accept函数
虚拟空打印时间(打印机*p)=0;
};
类打印机{
公众:
虚空打印(单据*d)=0;
//来访者
虚空打印(PDFDoc*d)=0;
虚拟作废打印(DocDoc*d)=0;
};
类PDFDoc:公共虚拟文档{
公众:
虚拟void printMe(打印机*p){

std::cout因为
printMe()
的参数是指向抽象基类
Printer
的指针:

virtual void printMe(Printer *p){
“双重分派”设计模式的目的是实现
print()
将适当的派生
文档
类作为参数传递

如果派生的
文档
类没有重载,基类中唯一的方法就是采用抽象
文档
基类的方法:

     p->print(this);
在没有额外重载的情况下,它只调用将virtual
文档
基类作为参数的同一个virtual方法

事件的顺序是:

  • 调用虚拟基类
    Printer
    ,参数为虚拟文档类
    document

  • 实际的打印机实现在从文档派生的实际类上使用

  • 因此,
    Document
    的纯虚拟
    printMe()
    方法从
    print()
    调用,该方法将
    Document
    指针作为参数

  • printMe()
    采用的唯一参数是虚拟
    Printer
    基类指针

  • 因此,无论
    printMe()
    调用什么,它都只能调用在虚拟
    Printer
    基类中定义的方法

  • 因此,如果实际的打印机实现需要使用派生的
    文档
    类,那么这些方法必须是
    打印机
    基类中的虚拟方法

  • 那些虚拟方法实际上不必是
    print()
    重载。它们可以是任何东西。对一些人来说,给它们起个不同的名字可能更清楚,比如
    printPDF()
    printDoc
    ()。如果你要重写它们,那么事情可能会更清楚


  • virtual void Printer::print(Document*d)=0;
    可能应重命名为
    print\u dispatch
    。作为
    MyPrinter
    中的文本记录该函数。