Làm thế nào để làm rõ rằng một chức năng đang được truy cập từ bên ngoài?


9

Đây là một câu hỏi cụ thể C. Tôi đang cố gắng giữ mọi thứ có thể bên trong ranh giới đơn vị dịch thuật, chỉ hiển thị một vài chức năng thông qua .htệp. Đó là, tôi đang đưa ra staticliên kết đến các đối tượng cấp tệp.

Bây giờ, một vài hàm cần được gọi bởi các mô-đun khác, nhưng không trực tiếp. Mô-đun / tệp / đơn vị dịch thuật của tôi đăng ký các mô-đun khác, chuyển một con trỏ đến một chức năng. Sau đó, trên một sự kiện cụ thể, con trỏ được gọi với một số đối số.

Vì vậy, tôi tự hỏi làm thế nào để làm cho nó rất rõ ràng rằng các chức năng được gọi từ một vị trí tối nghĩa.

  • Họ nên statichay extern(và phơi bày chúng trong .h)?
  • Tôi có nên bao gồm một số gợi ý trong tên của các chức năng?
  • Hoặc nó là đủ để đặt một bình luận "được gọi bởi X"?

1
Đó là một câu hỏi xuất sắc. Giải pháp của tôi (mà tôi không hài lòng chút nào, đó là lý do tại sao tôi chỉ đưa nó vào một bình luận) là tạo nhiều tệp tiêu đề, được đặt tên hợp lý và nhóm các chức năng trên phạm vi tôi muốn chúng có. Đối với thư viện AStar tôi đã tạo, tôi có AStar.h, AStar_private.h, AStar_packagePrivate.h, v.v ...
Shivan Dragon

Câu trả lời:


2

Từ quan điểm của đơn vị biên dịch (tệp), điều duy nhất bạn nên quan tâm là liệu chức năng có sẵn cho bên ngoài hay không. Làm cho nó khả dụng có nghĩa là nó đã được gọi và bạn nên vận hành theo giả định rằng những cuộc gọi đó sẽ xảy ra. Mối quan tâm của bạn với chức năng chính nó bắt đầu tại điểm vào của nó. Làm thế nào kiểm soát đến đó ở nơi đầu tiên chỉ quan trọng đối với mã làm cho nó xảy ra.

Vì liên kết trong mọi triển khai của CI đều là biểu tượng, nên bất cứ điều gì gọi hàm đều phải tham chiếu đến biểu tượng của nó:

foo();  /* Direct */

some_function_pointer_t funcs[] = { &foo, &bar, &baz };  /* Indirect */

Nếu bạn nhầm tuyên bố foo()static, chương trình của bạn sẽ không liên kết. Nếu bạn khai báo nó không- static, bạn có một hàm tiếp xúc không được gọi. Các câu hỏi về việc một hàm có được sử dụng hay không có thể được giải quyết bằng cách bỏ các bảng ký hiệu của các tệp đối tượng của bạn hoặc tìm kiếm nó trong các nguồn.


1

Vì vậy, tôi đang đi lang thang làm thế nào để làm cho nó rất rõ ràng rằng các chức năng đó được gọi từ một vị trí tối nghĩa.

Xác định "tối nghĩa".
Các phương thức nên được hiển thị thông qua các "giao diện" được xác định rõ và, như Shivan Dragon đã đề xuất, các "giao diện" đó các tệp .h của bạn. Nếu bạn không cung cấp cho chương trình khác tệp tiêu đề "đúng" thì nó không thể gọi phương thức.

Chúng nên tĩnh hay bên ngoài (và phơi chúng trong .h)?

static thể ổn miễn là bạn không có bất kỳ lớp [giống như cấu trúc] nào chứa dữ liệu cá thể.
externcó nghĩa là bạn hoàn toàn không thực hiện nó; một triển khai được "thu nhận" từ nơi khác trong quá trình liên kết.

Tôi có nên bao gồm một số gợi ý trong tên của các chức năng?

Hoặc nó là đủ để đặt một bình luận "được gọi bởi X"?

Tuyệt đối không.

Những bình luận như thế này, cho dù ý nghĩa tốt đến đâu, đều lỗi thời ngay khi bạn viết xong chúng.


Giải quyết điểm đầu tiên của bạn, các chức năng được gọi như sau. Thành phần của tôi bao gồm một .htập tin bên ngoài . Nó gọi một hàm từ đó và đưa cho nó một con trỏ tới một trong các hàm riêng của mô-đun. Sau đó, mã bên ngoài gọi bất cứ thứ gì ở con trỏ đó. Do đó, chức năng của tôi đang được ai đó gọi, người không bao gồm tệp tiêu đề của tôi, thay vào đó tôi bao gồm cả chức năng của mình.
Vorac

1
Liên quan đến điểm thứ hai, theo như sự hiểu biết của tôi, đối tượng, được xác định ở phạm vi tệp có liên kết bên ngoài theo mặc định; do đó externtừ khóa là dư thừa .
Vorac

0

Nếu các chức năng gọi lại được xác định trong mô-đun của bạn và người dùng sẽ không bao giờ cung cấp một chức năng của riêng mình, tôi nghĩ bạn có thể sử dụng trình giữ chỗ trong giai đoạn khởi tạo. Trình giữ chỗ thường là một enumcái mà sau đó được dịch nội bộ sang đúng staticchức năng.


0

Tôi vẫn sẽ tạo ra chúng static(chúng không có ý định liên kết và gọi bởi bất kỳ ai) và đánh dấu mục đích của chúng là các cuộc gọi lại được cung cấp cho các chức năng bên ngoài trong tên của chúng.

static bởi vì tôi cố gắng che giấu những gì tôi có thể che giấu, nhiều như tôi có thể che giấu nó.

Đánh dấu chúng trong tên của chúng, bởi vì a), các bình luận đã lỗi thời và b), điều đó trở nên rõ ràng tại nơi gọi lại được cung cấp rằng chức năng này được sử dụng theo cách đó: về cơ bản làm cho nó trở thành một cờ đỏ được lấy địa chỉ của một chức năng không tuân theo quy ước đặt tên.


0

Công cụ sửa đổi phạm vi nên được sử dụng chủ yếu làm thông tin cho trình biên dịch, chứ không phải là một dạng tài liệu "đủ gần". Việc sử dụng staticđặc biệt cho phép trình biên dịch C làm cho hàm không thể sử dụng được từ bên ngoài mô-đun, bao gồm cả gọi lại - không phải là điều bạn muốn, mặc dù nó có thể hoạt động với trình biên dịch hiện tại của bạn.

Tất nhiên bạn nên thêm một nhận xét vào mã, vì bạn có thể thấy đó là một tình huống có thể gây nhầm lẫn. Bất cứ điều gì bất thường hoặc bất ngờ cần một nhận xét phù hợp. Nhưng, như đã nêu trong các câu trả lời khác, các bình luận có thể không được đọc hoặc trở nên lỗi thời.

Vì vậy, tùy chọn duy nhất còn lại là đặt tên hàm để chỉ ra nó là một cuộc gọi lại. Hầu hết các ví dụ tôi đã thấy sử dụng _callbackhoặc _cbnhư một hậu tố, hoặc cb_như một tiền tố. Sử dụng biểu mẫu dài nếu các cuộc gọi lại không bình thường trong mã của bạn, biểu mẫu ngắn nếu chúng là phổ biến.

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.