Một cấu trúc C có thể hoạt động như nó có một chức năng?


13

Tôi sử dụng C và structs trong đó một cấu trúc có thể có các thành viên nhưng không có chức năng. Giả sử cho đơn giản rằng tôi muốn tạo một cấu trúc cho các chuỗi mà tôi đặt tên strvà tôi muốn có thể thực hiện str.replace(int i, char c)ở đâu ilà chỉ mục của chuỗi và clà ký tự để thay thế ký tự ở vị trí i. Điều này sẽ không bao giờ có thể xảy ra vì các cấu trúc không thể có chức năng hoặc vẫn có một số cách chúng ta có thể thực hiện hành vi này và bắt chước rằng một cấu trúc có thể có một chức năng (đơn giản) thực sự chỉ là cấu trúc sao chép chính nó sang một cấu trúc mới và cập nhật nó lĩnh vực, mà nó có thể làm gì?

Vì vậy, replacecó thể là thành viên thứ ba của cấu trúc trỏ đến một cấu trúc mới được cập nhật khi nó được truy cập hoặc tương tự. Nó có thể được thực hiện? Hoặc có một cái gì đó dựng sẵn hoặc một số lý thuyết hoặc mô hình ngăn cản ý định của tôi?

Bối cảnh là tôi đang viết mã C và tôi thấy mình đang phát minh lại các hàm mà tôi biết là các nội dung thư viện bằng ngôn ngữ OOP và OOP sẽ là một cách tốt để thao tác các chuỗi và lệnh.


5
Tôi thành thật nghĩ rằng bạn sẽ tốt hơn khi viết các hàm miễn phí để làm việc này. Tuy nhiên, nếu bạn có moxie cần thiết, hãy đọc cs.rit.edu/~ats/books/ooc.pdf
Robert Harvey

5
Cấu trúc có thể bao gồm các biến là con trỏ tới các hàm. Không được xây dựng trong kế thừa nhưng bạn có thể khởi tạo cấu trúc của mình bằng các con trỏ trỏ đến các hàm khác nhau có cùng chữ ký. Bạn thường muốn biến tham số đầu tiên cho hàm thành một con trỏ tới struct.
James McLeod

29
thay thế (& str, i, c) thực sự tệ hơn nhiều so với str.replace (i, c)? Câu hỏi của bạn không thực sự là về việc thay thế các chức năng, đó là về việc cố gắng làm mờ một cú pháp mới vào C.
whatsisname

1
@RobertHarvey Cảm ơn liên kết cs.rit.edu/~ats/books/ooc.pdf . Cuốn sách đẹp (và giá cả phù hợp).
John Forkosh

3
@whatsisname: Trong C, dù sao bạn cũng phải truyền con trỏ cấu trúc cho hàm, vì vậy cuối cùng bạn vẫn kết thúc str.replace(&str, i, c). C ++ tự động hóa việc vượt qua thiscon trỏ, tất nhiên.
Jonathan Leffler

Câu trả lời:


21

Chức năng của bạn sẽ trông như thế này.

void
replace(struct string * s, int i, char c);

Điều này chấp nhận một con trỏ đến đối tượng để hoạt động như là tham số đầu tiên. Trong C ++, điều này được gọi là this-pulum và không cần phải khai báo rõ ràng. (Tương phản điều này với Python nơi nó phải.)

Để gọi hàm của bạn, bạn cũng sẽ vượt qua con trỏ đó một cách rõ ràng. Về cơ bản, bạn giao dịch o.f(…)cú pháp cho f(&o, …)cú pháp. Không phải là một thỏa thuận lớn.

Câu chuyện trở nên liên quan hơn nếu bạn muốn hỗ trợ đa hình (còn gọi là các virtualhàm). Nó cũng có thể được mô phỏng bằng C (Tôi đã trình bày nó cho câu trả lời này .) Nhưng nó không đẹp để làm bằng tay.

Như Jan Hudec đã nhận xét, bạn cũng nên tạo thói quen đặt tiền tố tên hàm với tên loại (tức là string_replace) vì C không có không gian tên nên chỉ có thể có một hàm duy nhất được đặt tên replace.


17
Tất nhiên chức năng có thể sẽ phải được gọi string_replace, bởi vì C cũng không có chức năng quá tải và bạn có thể có một số khác replacecho một số loại khác
Jan Hudec

2
Nó không thể được đặt tên string_replace. Tên bắt đầu bằng str, memhoặc wcstheo sau là một chữ cái viết thường được dành riêng cho các phần mở rộng trong tương lai.
David Conrad

43

Cấu trúc có thể giữ chức năng con trỏ , nhưng chúng thực sự chỉ cần thiết cho các phương thức ảo. Các phương thức không ảo trong C hướng đối tượng thường được thực hiện bằng cách chuyển cấu trúc làm đối số đầu tiên cho hàm thông thường. Hãy xem Gobject để biết một ví dụ hay về khung OOP cho C. Nó sử dụng các macro để xử lý rất nhiều bản mẫu cần thiết cho tính kế thừa và đa hình.

C đã được tạo ra 44 năm trước. Đó là một ngôn ngữ rất phổ biến cho nguồn mở. Bạn không phải là người đầu tiên nghĩ rằng chuỗi C tiêu chuẩn rất khó để làm việc. Thực hiện một số tìm kiếm cho các thư viện chuỗi C. Bạn không phải phát minh lại bánh xe.


2
Ví dụ đáng chú ý khác là CPython. Mã này sử dụng rất nhiều khái niệm OOP nhưng nó hoàn toàn 100% C.
Bakuriu

@Bakuriu Tôi nghĩ bạn đang nhầm lẫn CythonCPython
mèo

1
@cat Anh ấy có thể có nghĩa là API Python C, Cython không hoàn toàn 100% C. docs.python.org/c-api/intro.html
JAB

5
@cat Không. Hãy nhìn vào nguồn CPython. Hầu hết mọi thứ thực sự được thực hiện bằng mô hình OOP và chúng cung cấp API OOP hầu hết phù hợp với API python.
Bakuriu

1
@Bakuriu Ồ, ý bạn là API thời gian chạy, nguồn và C của Python không phải là ngôn ngữ Python. bình luận của bạn đã không làm cho điều đó rất rõ ràng
con mèo

8

Với con trỏ hàm, bạn có thể làm:

str.replace(&str, i, c);

Điều này thường chỉ hữu ích nếu việc triển khai có thể thay đổi, trong trường hợp đó bạn nên sử dụng vtable để chi phí chỉ là một con trỏ trên mỗi struct:

str.vtable->replace(&str, i, c);

3
Tôi có xu hướng vẫn gọi nó là chuỗi numplace (& str, i, c) sau đó sử dụng vtable bên trong chuỗi numplace thay vì để trang web cuộc gọi biết về vtable.
Pete Kirkham

2
@Pete Tên bắt đầu bằng str(hoặc memhoặc wcs) và một chữ cái viết thường được dành riêng cho tiêu chuẩn C cho các tiện ích mở rộng trong tương lai, vì vậy đừng gọi nó string_replace. str_replaceỔn.
David Conrad

3

Vâng, họ có thể, loại. Bạn có thể sử dụng thực tế là C cho phép con trỏ thực hiện các khối chức năng trong bộ nhớ, còn gọi là con trỏ hàm và sử dụng rằng bạn có thể tạo giao diện như đa hình cũng như các hàm ảo (ngay cả khi nó không đẹp).

Tôi đã viết một bài đăng trên blog về chủ đề này, sau một câu hỏi của một trong những học sinh của tôi, gần đây, liên quan đến mã giống như giao diện trong C và Go, bạn có thể đọc nó ở đây:

Bài đăng trên blog về giao diện không OO

Xem nếu nó cung cấp cho bạn bất kỳ ý tưởng.

Bạn cũng có thể chỉ cần đặt một hàm miễn phí trong mã của mình và sử dụng con trỏ "này", nghĩa là bạn chuyển một con trỏ đến một cấu trúc hiện có để làm việc, như được mô tả trong các câu trả lời khác.

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.