2013-06-19 15 views
7

Tôi đã nhìn thấy một vài ví dụ minh họa mẫu khách truy cập. Trong tất cả chúng, mỗi phần tử truy cập có nguồn gốc thực hiện những gì thường được gọi là phương thức Accept().C++ mô hình khách truy cập: Tại sao mọi truy xuất có nguồn gốc đều được truy cập Accept()?

Trong một hệ thống các màu sắc, phương pháp này có thể trông giống như:

void Red::accept(Visitor *v) 
{ 
    v->visit(*this); 
} 

void Blue::accept(Visitor *v) 
{ 
    v->visit(*this); 
} 

Khi khách, cũng như những người thừa kế của nó, có những phương pháp:

visit(Red red); 
visit(Blue blue) 

Câu hỏi của tôi là tại sao không thực hiện điều này trong cùng một cách chỉ trong lớp cơ sở (trong ví dụ này: Color) và đa hình sẽ thực hiện công việc, cụ thể là, lượt truy cập chính xác sẽ được gọi kể từ khi đối tượng là Red loại động này là Red để dereferencing nó sẽ mang lại một số Red do đó sẽ làm cho chuyến thăm (đỏ) được gọi?

Tôi đang thiếu gì?

+4

nếu bạn muốn trong lớp cơ sở thì bạn phải sử dụng [Mẫu mẫu tò mò định kỳ] (https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) để có được quyền 'this'. – user1810087

+0

Trong ngôn ngữ động hơn, bạn có thể phải đặt tên cho các hàm 'visitBlue' và' visitRed'. Bạn có thể làm điều đó ở đây là tốt. Điều đó có giúp nó có ý nghĩa không? –

+1

Câu trả lời đã được cung cấp, nhưng bạn có thể tìm thêm thông tin tìm kiếm trên web để "gửi đôi" (Tôi cho rằng bạn đã tìm kiếm "mẫu khách truy cập" và nó không giúp bạn), là tên của kỹ thuật được sử dụng đây. –

Trả lời

8

Đa hình thừa kế (công văn động) không áp dụng cho đối số hàm. Nói cách khác, chức năng quá tải được chọn trên kiểu tĩnh của các đối số được truyền. Nếu được triển khai trong lớp cơ sở Color, thì v->visit(*this) sẽ luôn gọi visit(Color c).

+0

Rõ ràng và đúng điểm. Điều làm tôi bối rối là khi tôi có một hàm không phải ảo và tôi gọi hàm ảo từ bên trong nó, tính đa hình sẽ hoạt động và ảo của người thừa kế sẽ được gọi nếu tồn tại như vậy. – Subway

+1

Tôi sẽ chỉnh sửa nó thành "không áp dụng cho đối số chức năng được truyền theo giá trị" (vì nếu bạn vượt qua tham chiếu ** và ** bạn có đúng chức năng ảo, thì nó sẽ áp dụng) ... – Massa

+1

@Massa, tôi tin bạn nhầm rồi Tham khảo hay không, đó là các kiểu tĩnh của các đối số được sử dụng để chọn hàm quá tải nào sẽ được gọi. Không có công văn kép trong C++, nó chỉ được mô phỏng bởi mẫu khách truy cập này. http://en.wikipedia.org/wiki/Double_dispatch – rectummelancolique

1

Nếu chỉ accept bạn có là ...

void Color::accept(Visitor* v) 
{ 
    v->visit(*this); 
} 

visit sẽ chỉ được gọi với một lớp cơ sở. Để gọi visit với lớp dẫn xuất chính xác bạn cần mỗi Color để triển khai nó để chúng có thể vượt qua một cách chính xác được nhập this, do đó, quá tải chính xác visit được gọi.

1

Sự hiểu biết của tôi là trong các phương thức lớp cơ sở con trỏ this là loại cơ sở, không phải của bất kỳ lớp dẫn xuất nào, do đó nó chỉ có thể truy cập các phương thức lớp cơ sở và được chuyển thành loại Color* this. Khi được chuyển sang phương thức truy cập, nó sẽ thử và chạy visit(Color* color), vì hành vi đa hình chỉ áp dụng cho các phương thức của chính lớp đó (không phải các lớp khác).

+0

Cái gì, cái gì, cái gì? –

+0

Khi tôi có trong cơ sở một chức năng phi ảo và tôi gọi một chức năng ảo từ bên trong nó, đa hình sẽ làm việc và ảo của người thừa kế sẽ được gọi nếu tồn tại như vậy, phải không? – Subway

+0

Có, nhưng trong trường hợp đó, nó có quyền truy cập vào vtable, xử lý công văn động đó. Đó là một trường hợp đặc biệt không áp dụng trên các lớp không liên quan như được sử dụng trong mẫu Khách truy cập. – Utopia