C++ 双重分派示例
C++ double dispatch example
我得到这段代码作为使用双重分派的示例,但我并不真正理解其中的一部分代码。创建 "abstract class" 打印机,为什么我需要添加:
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?
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;
}
因为printMe()
的参数是指向抽象基class的指针,Printer
:
virtual void printMe(Printer *p){
而 "double-dispatch" 设计模式的目的是实现 print()
传递适当的派生 Document
class 作为参数。
没有派生 Document
classes 的重载,基 class 中唯一的方法是采用抽象 Document
基 class:
p->print(this);
在没有额外重载的情况下,这只是调用以虚拟 Document
基础 class 作为参数的相同虚拟方法。
事件的顺序是:
虚拟基础 class Printer
被调用,参数是虚拟文档 class Document
.
实际打印机实现使用派生自文档的实际 class。
因此,Document
的纯虚拟 printMe()
方法被调用,来自 print()
,它将 Document
指针作为参数。
printMe()
接受的唯一参数是虚拟Printer
基class指针。
所以,无论printMe()
调用什么,都只能调用virtual Printer
base中定义的方法class.
因此,如果实际的打印机实现需要使用派生的Document
class,那些方法必须是Printer
基[=]中的虚方法75=].
那些虚拟方法并不一定要 print()
重载。它们可以是任何东西。对某些人来说,将它们命名为不同的名称可能更清楚,例如 printPDF()
和 printDoc
()。如果您要重写它们,那么可能会更清楚发生了什么。
我得到这段代码作为使用双重分派的示例,但我并不真正理解其中的一部分代码。创建 "abstract class" 打印机,为什么我需要添加:
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?
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;
}
因为printMe()
的参数是指向抽象基class的指针,Printer
:
virtual void printMe(Printer *p){
而 "double-dispatch" 设计模式的目的是实现 print()
传递适当的派生 Document
class 作为参数。
没有派生 Document
classes 的重载,基 class 中唯一的方法是采用抽象 Document
基 class:
p->print(this);
在没有额外重载的情况下,这只是调用以虚拟 Document
基础 class 作为参数的相同虚拟方法。
事件的顺序是:
虚拟基础 class
Printer
被调用,参数是虚拟文档 classDocument
.实际打印机实现使用派生自文档的实际 class。
因此,
Document
的纯虚拟printMe()
方法被调用,来自print()
,它将Document
指针作为参数。printMe()
接受的唯一参数是虚拟Printer
基class指针。所以,无论
printMe()
调用什么,都只能调用virtualPrinter
base中定义的方法class.因此,如果实际的打印机实现需要使用派生的
Document
class,那些方法必须是Printer
基[=]中的虚方法75=].那些虚拟方法并不一定要
print()
重载。它们可以是任何东西。对某些人来说,将它们命名为不同的名称可能更清楚,例如printPDF()
和printDoc
()。如果您要重写它们,那么可能会更清楚发生了什么。