我获得了此代码作为使用双重调度的示例,但是我并不真正理解代码的一部分。创建“抽象类”打印机,为什么需要添加:
virtual void print(PDFDoc *d)=0;
virtual void print(DocDoc *d)=0;
据我了解,在运行时p.print(docA);
会将我发送到myPrinter的virtual void print(Document *d)
,然后d->printMe(this)
会将我发送到PDFDoc的printMe,然后它将在运行时调用virtual void print(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;
}
答案 0 :(得分:2)
因为printMe()
的参数是抽象基类Printer
的指针:
virtual void printMe(Printer *p){
“双调度”设计模式的目的是实现print()
并将适当的派生Document
类作为参数传递。
没有派生的Document
类的重载,基类中的唯一方法是采用抽象Document
基类的方法:
p->print(this);
在没有其他重载的情况下,这仅调用将虚拟Document
基类作为参数的同一虚拟方法。
事件的顺序是:
调用虚拟基类Printer
,其参数为虚拟文档类Document
。
实际的打印机实现用于派生自Document的实际类。
因此,从Document
中调用printMe()
的纯虚拟print()
方法,该方法将Document
指针作为参数。
printMe()
唯一的参数是虚拟的Printer
基类指针。
因此,无论printMe()
调用什么,它都只能调用虚拟Printer
基类中定义的方法。
因此,如果实际的打印机实现需要使用派生的Document
类,则这些方法必须是Printer
基类中的虚拟方法。
这些虚拟方法实际上不必是print()
重载。他们可以是任何东西。对于某些人来说,更清楚地命名它们是不同的,例如printPDF()
和printDoc
()。如果您这样重写它们,可能会更清楚发生了什么。