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
中的文本记录该函数。