Công văn là gì? Liệu nó ngụ ý độ phân giải động?


8

AFAIK, công văn hạn có nghĩa chỉ là một giải pháp phương thức và gọi. Nó không quan trọng cho dù đó là tĩnh hay động. Tôi thấy nhiều người đang sử dụng một thuật ngữ như công văn tĩnh và công văn động .

Điều khiến tôi bối rối là cũng có một số mô tả bí ẩn. Tôi đã cố gắng hiểu thế nào là nhiều công văn và dường như chỉ cần chọn một chương trình con theo các loại tham số . Nếu tôi hiểu nó một cách chính xác, có thể có cả hai nhiều công văn tĩnhnhiều công văn năng động , và chúng ta có thể nói C ++ đang cung cấp nhiều công văn qua chức năng miễn phí.

Nhưng, bài viết trên Wikipedia về nhiều công văn nói rằng C ++ không có nhiều công văn vì nó không có độ phân giải động của chức năng theo nhiều tham số. Và tôi thực sự không nhận được sự khác biệt về khái niệm giữa ví dụ Common Lisp và hàm quá tải C ++. Bởi vì tôi không thể tìm thấy bất kỳ sự khác biệt về khái niệm trừ khi thuật ngữ nhiều công văn ngụ ý công văn động . Và tôi nhận ra rằng tôi đang bối rối không biết việc gửi đi thực sự là gì

Tôi cũng đã kiểm tra mục nhập QA Nhiều công văn so với quá tải chức năng và có vẻ như câu trả lời là tiền đề cho công văn về cơ bản là động . Điều đó cũng khiến tôi bối rối.

Ý nghĩa chính xác của công văn hạn là gì? Liệu nó ngụ ý độ phân giải động ? Là thuật ngữ này được xác định rõ hay chỉ là thông thường? Tôi đang thiếu gì?


1
"Bài viết trên Wikipedia về nhiều công văn nói rằng C ++ không có nhiều công văn" - bạn đang đề cập đến bài viết nào? C ++ không có nhiều công văn. Và vâng, nhiều công văn không ngụ ý động (xem en.wikipedia.org/wiki/Mult Môn_dispatch )
miraculixx

@miraculixx Đó là bài viết. Và bài viết Wikipedia không đề cập đến thuộc tính tĩnh / động, vì vậy tôi hoàn toàn bối rối.
Eonil

1
@miraculixx - C ++ không có nhiều công văn. Bạn phải giả mạo nó với một số mẫu thiết kế như Mẫu khách truy cập.
David Hammen

@David thực sự, tôi đoán rằng tôi đã nhầm lẫn ở đó, và trong một khoảnh khắc ngắn, trộn lẫn quá tải chức năng (mà c ++ thực hiện tĩnh) và đa công văn. errare humanum est ...
miraculixx

Câu trả lời:


12

Các thuật ngữ có nghĩa như sau:

  • công văn tĩnh = thứ tự công văn được xác định tại thời gian biên dịch . Nó đơn giản có nghĩa là bất kỳ lệnh gọi hàm / phương thức nào nói foo()hoặc x.foo()sẽ luôn gọi hàm tương tự - điều này được thiết lập một lần và sau đó giữ nguyên như vậy. Điều này ngụ ý rằng trình biên dịch có thể xác định loại xtại thời gian biên dịch.

  • công văn động = thứ tự công văn được giải quyết trong thời gian chạy . Điều này có nghĩa là trình biên dịch xây dựng một bảng tra cứu tất cả các hàm / phương thức và xác định cái nào sẽ thực sự gọi trong thời gian chạy. Giả sử có lớp A và B, cả hai đều thực hiện giao diện X với phương thức X.bar(). Trong thời gian chạy, yđược kiểm tra và dựa trên lớp thực tế của nó A.bar()hoặc B.bar()được gọi.

  • nhiều công văn động = thứ tự công văn phụ thuộc vào tên hàm / phương thức + loại đối số (= aka chữ ký ) và việc triển khai thực tế được gọi được xác định động khi chạy. Nói lớp A thực hiện các phương thức A.fooBar(int)A.fooBar(char *), và có một cuộc gọi đến a.fooBar(x)trong chương trình của bạn. Trong thời gian chạy cả hai axđược kiểm tra và phương thức thực tế để gọi được xác định dựa trên loại x.

Xem Wikipedia để biết thêm về công văn độngnhiều công văn động .


1
Tôi có thể xử lý các chức năng miễn phí C ++ đang hỗ trợ nhiều công văn tĩnh không?
Eonil

tốt, theo định nghĩa không - nhiều công văn ngụ ý động. Với các hàm miễn phí c ++, AFAIK trình biên dịch thực hiện tất cả các công việc thực sự là công văn tĩnh luôn nhìn vào tên hàm + chữ ký.
miraculixx

1
Nếu thuật ngữ công văn có thể được sử dụng trên cả tĩnh và động, tại sao nhiều công văn có nghĩa là động? Điều gì về nhiều công văn tĩnh ?
Eonil

1
công văn tĩnh có nghĩa là trình biên dịch xây dựng một bảng tra cứu tất cả các chức năng, bao gồm cả chữ ký. Bất kỳ công văn tĩnh nào cũng có hiệu quả nhiều công văn, vì vậy theo quy ước khi bạn nói nhiều công văn mọi người sẽ cho rằng bạn ngụ ý động .
miraculixx

@miraculixx Không phải tất cả các công văn tĩnh là nhiều công văn. Đó là trường hợp trong C ++ nhưng không nói chung.
dùng253751

12

Lời khuyên của tôi ở đây là: đừng lật đổ cái này. Công văn chỉ đơn giản là gửi. Gửi một sự kiện đến người nghe, gửi một ngắt cho người xử lý, gửi tin nhắn đến người nhận, gửi một cuộc gọi đến một thủ tục hoặc chức năng: tất cả các khía cạnh của cùng một khái niệm cơ bản. Gửi dữ liệu đến mã sẽ xử lý nó. Nghị quyết có nghĩa là lựa chọn giữa các điểm đến có sẵn, và chỉ là một phần của công văn.

Về mặt mã, công văn bắt đầu với một số loại thông tin và một cái gì đó cho biết nơi cần gửi và kết thúc khi gói đã được gửi (được gửi đi). Tất cả các ngôn ngữ đều có một số loại cơ chế điều phối được xây dựng, nhưng nhiều ngôn ngữ thực hiện các kế hoạch phân giải và điều phối để phù hợp với một mục đích duy nhất. Xử lý ngắt và xử lý tin nhắn windows là những ví dụ xuất hiện trong tâm trí.

C ++ có thể sử dụng độ phân giải tĩnh hoặc động, nhưng nếu nó chọn giữa các hàm dựa trên các loại đối số thì nó chỉ có thể làm như vậy tại thời gian biên dịch. Smalltalk / Objective C và Ruby giải quyết các công văn trong thời gian chạy, cũng như nhiều ngôn ngữ động.

Công văn đơn có nghĩa là một đối số duy nhất được coi là người nhận và xác định phương thức nào được gọi. Phương thức này thường nằm trong lớp cho đối tượng người nhận đó và chữ ký phương thức được chuyển đổi thành phần bù trong bảng công văn (vtable) trong lớp đó. Đối tượng đặc quyền trong C ++ là đối tượng trước dấu chấm, trở thành con trỏ 'this'.

Nhiều công văn có nghĩa là không có người nhận đặc quyền nhưng thường là một hoạt động khớp mẫu trên tất cả các loại đối số. Hệ thống đối tượng Lisp chung sử dụng phương pháp này. Xem https://en.wikipedia.org/wiki/Mult Môn_dispatch .

Trong C ++ với các toán tử quá tải, A + B và B + A phải gửi đến các phương thức khác nhau. Trong CLOS họ có thể giống nhau.

Tôi có lẽ thích thuật ngữ MultiMethod hơn, vì nó có độ phân giải đa yếu tố hơn là nhiều công văn mỗi se. Xem http://c2.com/cgi/wiki?MultiMethods . Ngoài ra http://www.codeproject.com/Articles/242749/Multipl-dispatch-and-double-dispatch .


1
"C ++ có thể sử dụng độ phân giải tĩnh hoặc động ... nó chỉ có thể làm như vậy vào thời gian biên dịch", còn phương thức ảo thì sao? Chúng được xác định linh hoạt trong thời gian chạy và phụ thuộc vào chữ ký phương thức
miraculixx

Hy vọng rằng chỉnh sửa của tôi làm cho nó rõ ràng hơn những gì tôi dự định.
david.pfx

0

C ++ không có nhiều công văn (động). Hãy xem xét những điều sau đây:

#include <iostream>

struct Foo {
   virtual ~Foo() {}
};

struct FooOne : public Foo {};

struct Bar {
   virtual ~Bar() {}
   virtual void dispatch (const Foo &) {
      std::cout << "Bar::Dispatch(const Foo &)\n";
   }
};

struct BarOne : public Bar {
   using Bar::dispatch;
   virtual void dispatch (const Foo &) {
      std::cout << "BarOne::Dispatch(const Foo &)\n";
   }
   virtual void dispatch (const FooOne &) {
      std::cout << "BarOne::Dispatch(const FooOne &)\n";
   }
};

void process (Bar & bar, const Foo & foo) {
   bar.dispatch (foo);
}

int main () {
   Foo foo;
   Bar bar;
   FooOne foo_one;
   BarOne bar_one;

   process (bar, foo);
   process (bar, foo_one);

   process (bar_one, foo);
   process (bar_one, foo_one);

   bar_one.dispatch (foo_one);

   return 0;
}

Đầu ra từ trên là

Bar::Dispatch(const Foo &)
Bar::Dispatch(const Foo &)
BarOne::Dispatch(const Foo &)
BarOne::Dispatch(const Foo &)
BarOne::Dispatch(const FooOne &)

Trong process(Foo& foo, const Bar& bar), C ++ sử dụng công văn động trên đối số footrong câu lệnh foo.dispatch(bar). Các dòng đầu ra thứ ba và thứ tư hiển thị công văn động kiểu C ++ này đang hoạt động. Dòng đầu ra thứ tư chứng tỏ rằng C ++ không có nhiều công văn. Nếu có, dòng đầu ra thứ tư đó sẽ giống như dòng cuối cùng.

Dòng cuối cùng đó? Đó là công văn tĩnh. Trình biên dịch biết tại thời điểm biên dịch chính xác hàm nào cần được gọi. Cuộc gọi cuối cùng này không đi qua bảng ảo.


Ví dụ này là hợp lệ và hữu ích, nhưng nhiều công văn hay còn gọi là multimethods đi xa hơn. Trong một ngôn ngữ gửi đến một người nhận lớp duy nhất, bạn thậm chí không thể viết loại ví dụ xuất hiện tự nhiên trong CLOS.
david.pfx
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.