2010-07-16 30 views
7

tôi đã viết mô hình khách truy cập như sau nhưng tôi không hiểu những gì là đơn và đôi công văn. AFAIK, công văn đơn được gọi một phương thức dựa trên loại người gọi, nơi công văn kép gọi một phương thức dựa trên kiểu người gọi và loại đối số.Công văn đơn và đôi là gì?

Tôi đoán công văn kép xảy ra trong phân cấp lớp đơn nhưng tại sao lớp khách truy cập có hai phân cấp lớp nhưng nó vẫn được coi là công văn kép.

void floppyDisk::accept(equipmentVisitor* visitor) 
{ 
visitor->visitFloppyDisk(this); 
} 

void processor::accept(equipmentVisitor* visitor) 
{ 
visitor->visitProcessor(this); 
} 

void computer::accept(equipmentVisitor* visitor) 
{ 
BOOST_FOREACH(equipment* anEquip, cont) 
{ 
    anEquip->accept(visitor); 
} 

visitor->visitComputer(this); 
} 

void visitFloppyDisk(floppyDisk*); 
void visitProcessor(processor*); 
void visitComputer(computer*); 

Vui lòng giải thích bằng mã ví dụ tôi đã cung cấp.

AFAIK, công văn đầu tiên xảy ra trên đối tượng người gọi chấp nhận và công văn thứ hai xảy ra trên đối tượng người gọi phương thức truy cập.

Cảm ơn.

+0

Có lẽ đọc này [bài viết ] (http://en.wikipedia.org/wiki/Multiple_dispatch) có thể giúp bạn hiểu công văn - không phải cách nó được triển khai trong C++, nhưng khái niệm –

Trả lời

9

Trong ngắn hạn, một công văn là khi một phương pháp đa hình trên loại của một tham số (bao gồm cả ngụ ý this). Công văn kép là đa hình trên hai tham số.

Ví dụ điển hình cho phương án đầu tiên là phương pháp ảo chuẩn, đa hình về loại đối tượng chứa. Và thứ hai có thể được thực hiện thông qua mẫu Visitor.

[cập nhật] tôi cho rằng trong ví dụ của bạn, floppyDisk, processorcomputer mỗi kế thừa từ một lớp cơ sở chung trong đó xác định accept như một phương pháp ảo. Tương tự, các phương thức visit* phải được khai báo ảo trong equipmentVisitor, cần có một số lớp dẫn xuất có triển khai visit* khác nhau. [/ cập nhật]

Giả sử trên, accept là đa hình trên cả thisequipmentVisitor. Các floppydisk, bộ vi xử lý và máy tính từng có thực hiện riêng của họ accept, vì vậy khi khách truy cập gọi accept, cal được gửi dựa trên loại của callee. Sau đó, callee gọi lại phương thức truy cập cụ thể của loại khách truy cập và cuộc gọi này được gửi dựa trên loại thực tế của khách truy cập. Về lý thuyết, có thể có công văn gấp ba, gấp bốn lần vv, mặc dù tôi chưa bao giờ thấy điều này được thực hiện trong thực tế (bằng các ngôn ngữ không hỗ trợ công văn gấp đôi và cao hơn) - dường như tôi nhớ rằng Smalltalk làm?). Công văn đôi khi sử dụng Visitor in C++ và các ngôn ngữ tương tự đã hoàn toàn tự phát triển, do đó việc thực hiện các công văn ba và cao hơn sẽ đơn giản là quá phức tạp để sử dụng trong các ứng dụng thực.

+1

+1, nhiều công văn bằng các ngôn ngữ không hỗ trợ nó một cách tự nhiên viết tất cả các kết hợp, và tăng trưởng theo cấp số nhân với số lượng đối số để gửi đi, đó là một lý do khá tốt để tránh né nó. –

6

Trong ví dụ của bạn, bạn thiếu những điều cơ bản về cơ chế: kế thừa và tính ảo. Giả sử hệ thống phân cấp lớp sau, ngoài việc mã của bạn:

class equipmentVisited 
{ 
    virtual void accept(equipmentVisitor* visitor) = 0; 
} 

class floppyDisk : public equipmentVisited 
{ 
    virtual void accept(equipmentVisitor* visitor); 
} 

class processor : public equipmentVisited 
{ 
    virtual void accept(equipmentVisitor* visitor); 
} 

class computer : public equipmentVisited 
{ 
    virtual void accept(equipmentVisitor* visitor); 
} 

class equipmentVisitor 
{ 
    virtual void visitFloppyDisk(floppyDisk*); 
    virtual void visitProcessor(processor*); 
    virtual void visitComputer(computer*); 
} 

// Some additional classes inheriting from equipmentVisitor would be here 

Bây giờ, hãy tưởng tượng bạn có đoạn mã này trong một số chức năng:

equipmentVisited* visited; 
equipmentVisitor* visitor; 
// ... 
// Here you initialise visited and visitor in any convenient way 
// ... 
visited->accept(visitor); 

Nhờ cơ chế văn đôi, dòng cuối cùng này cho phép bất kỳ equipmentVisited chấp nhận bất kỳ equipmentVisitor nào, bất kể loại tĩnh thực tế của chúng là gì. Cuối cùng, hàm đúng sẽ được gọi cho lớp phù hợp.

Để tóm tắt:

  • Công văn đầu tiên gọi accept() trên lớp phù hợp
  • Công văn thứ hai gọi hàm thích hợp trên lớp bằng công văn đầu tiên được chọn
Các vấn đề liên quan