2011-01-18 67 views
12

Sau khi đọc câu trả lời của sbi và Eli Bendersky trong this question Tôi bắt đầu tự hỏi các chức năng thành viên tĩnh là gì.Chức năng thành viên tĩnh

Chức năng miễn phí của bạn bè của một lớp không được có thể làm bất cứ điều gì chức năng thành viên tĩnh có thể làm gì? Nếu vậy, tại sao/khi nào tôi nên sử dụng chức năng thành viên tĩnh cho một người bạn miễn phí?

+0

Thường thì, thẳng thắn, bạn không nên. –

Trả lời

12

Nói chung:

Yêu cầu quyền truy cập vào các thành viên private

hàm thành viên tĩnh được tiếp cận với các thành viên private của lớp. Nếu bạn cần điều đó, bạn có thể sử dụng một hàm thành viên tĩnh. Bạn phải khai báo nó trong tiêu đề để cho nó truy cập, vì vậy bạn cũng có thể biến nó thành một thành viên thay vì một người bạn. Nó thường được thực hiện theo cách này cho các singletons có phương thức getInstance() là singleton và các lớp sử dụng phương thức createInstance() để đảm bảo chúng được tạo trên heap. Cả hai đều cần truy cập vào hàm tạo riêng.

Meta-lập trình

hàm thành viên tĩnh là rất tốt cho mẫu meta-lập trình, nơi bạn có thể vượt qua trong một lớp và gọi phương thức của nó mà không biết tại thời điểm gọi gì chức năng thực sự sẽ nhận được viện dẫn. Điều này thường được gọi là "đa hình thời gian biên dịch" và là một phần quan trọng của lập trình meta. std :: char_traits dựa trên nguyên tắc này.

truy cập Restricted

Việc sử dụng phổ biến của một hàm thành viên tĩnh tư nhân, chỉ để nó có thể được truy cập chỉ bởi lớp, và không tự nó cần truy cập vào các thành viên tư nhân, không phải là một sử dụng tốt các hàm thành viên tĩnh vì nó là một phần của chi tiết thực hiện của lớp và điều này được thực hiện tốt hơn trong vùng tên ẩn danh của đơn vị biên dịch.

Tuy nhiên, nếu chức năng thành viên tĩnh là được bảo vệ, nó có thể sử dụng vì nó có thể được gọi bởi các lớp dẫn xuất chứ không phải bởi các lớp bên ngoài.

hàm friend

  • có thể có quyền truy cập cho các thành viên riêng nhưng cần phải được khai báo trong tiêu đề anyway.
  • Có thể được sử dụng trong lập trình meta như một phần của "quá tải" tuy nhiên vẫn cần được khai báo trong tiêu đề. (Ví dụ chung là operator<<)
  • Không hoạt động để truy cập được bảo vệ với tình bạn như những gì bạn đang cố gắng làm ở đây là hạn chế quyền truy cập vào phương thức, chứ không phải những gì cuộc gọi có quyền truy cập.
+0

Trong trường hợp nào bạn không thể sử dụng các chức năng miễn phí của người bạn trong mẫu meta-programming? Không thể tìm thấy bất kỳ ví dụ nào trong đó một chức năng miễn phí của bạn bè sẽ không thể thực hiện điều gì đó mà một hàm thành viên tĩnh có thể thực hiện. Điểm thứ ba là một điểm tốt, không nghĩ về nó! Ví dụ: – peoro

+0

các lớp đặc điểm. traits_class :: dostuff (params); dostuff là thành viên tĩnh của traits_class. – CashCow

+0

Trong câu trả lời ở trên, traits_class là tham số mẫu hoặc được lấy từ tham số mẫu. – CashCow

4

Thường thì, thẳng thắn, bạn không nên. Các chức năng miễn phí là bao la không được xếp hạng.

"Không gian tên" ngầm định bạn nhận được từ việc sử dụng thành viên tĩnh (giả vờ rằng lớp không là gì hơn không gian tên cho thành viên tĩnh, là loại đúng) là lợi ích duy nhất mà tôi có thể nghĩ đến.

Nếu thành viên chức năng tĩnh cần biến cố định, khả năng có các thành viên dữ liệu tĩnh cùng với nó cũng có thể hữu ích.

+0

+1 cho "Các chức năng miễn phí được đánh giá rất thấp." –

10

phương pháp tĩnh:

  • Cung cấp đóng gói trong "không gian tên" tạo bởi lớp. Nếu lớp học của bạn là Animal và phương pháp tĩnh là Create, bạn phải gọi nó là Animal::Create. Điều này tốt hơn các chức năng toàn cầu, và cho phép triển khai các Nhà máy và "các nhà thầu ảo" với cú pháp tương đối tự nhiên.
  • Có quyền truy cập vào các thành viên tĩnh. Các thành viên như vậy hữu ích trong một số trường hợp, và không có các phương thức tĩnh và các thành viên, bạn sẽ phải sử dụng các biến và hàm toàn cầu.
+1

Ngoài ra, nếu có một thể hiện của lớp, chúng cũng có quyền truy cập vào tất cả các phương thức và chức năng riêng. Điều này rất hữu ích" – Macke

+0

Thành viên lớp tĩnh cũng hiển thị trong các chức năng miễn phí. Bạn nói đúng về điểm đầu tiên, nhưng nó chỉ là một vấn đề cú pháp, phải không? Điều này không tương phản với những điều được nói trong câu hỏi khác? – peoro

+0

@peoro: (1) chủ yếu là về việc đặt tên, Không thuận tiện để có một phương thức tĩnh * bên trong * một lớp, nếu không bạn có liên quan như thế nào với người dùng rằng nó là một phần của lớp một cách hợp lý? cách truy cập các thành viên tĩnh hơn là có các hàm toàn cục và khai báo chúng trong lớp, IMHO –

3

Một số người cảnh giác với việc sử dụng các hàm tĩnh vì nó thường được sử dụng bởi những người đến từ nền tảng thủ tục và không hiểu OO.

Tuy nhiên, có nhiều mẫu thiết kế có ý nghĩa khi được triển khai bằng các hàm thành viên tĩnh

Ví dụ: Singleton và Nhà máy mô hình để đặt tên một vài đầu của tôi đầu, trên thực tế hầu hết các mô hình cấu trúc đòi hỏi phải tạo đối tượng sẽ yêu cầu các chức năng thành viên tĩnh.

+1

có, chức năng tĩnh được sử dụng cho mục đích này, nhưng bạn bè chức năng miễn phí sẽ có thể làm tương tự mà không có bất kỳ bất lợi ... – peoro

+0

Nhưng cũng hãy cẩn thận của dữ liệu toàn cầu được ngụy trang thông qua một singleton. Xem thảo luận phong phú về SO ở đây: http://stackoverflow.com/questions/137975/… - rholmes vừa chỉnh sửa – rholmes

1

Không có giá trị gia tăng nào cho static chức năng thành viên, như bạn đã xác định chính xác. Tồi tệ hơn, khi được sử dụng để thực hiện chi tiết, điều này giới thiệu thêm phụ thuộc (trong thời gian biên dịch).

Chỉ sử dụng không thể mô phỏng bằng chức năng miễn phí ẩn danh, là quyền truy cập protected, tức là lớp dẫn xuất truy cập chức năng tĩnh gốc. Tuy nhiên, điều này là không bao giờ cần thiết: bạn chỉ có thể làm cho nó một chức năng thành viên thường xuyên thay vào đó (tôi giả sử bạn không có nhà nước toàn cầu, nếu không sự phân biệt tĩnh/người bạn không phải là mối quan tâm ngay lập tức).

Việc sử dụng các chức năng static trong lập trình meta mẫu đã được gợi lên ... tuy nhiên nó rất giống với vấn đề loại bên trong: nó gây khó khăn cho việc cung cấp phiên bản mặc định. Mặt khác, một chức năng miễn phí được xác định phù hợp (trong đó có các loại như một con trỏ), có thể đề xuất một mẫu phiên bản:

struct some_traits 
{ 
    static void doStuff(); 
}; 

// versus 

struct some_traits {}; 

void doStuff(some_traits*); 

// and the default: void doStuff(...); 

Và tất nhiên, luôn là câu hỏi về lý do tại sao điều này sẽ là một hàm tĩnh , khi một chức năng thành viên sẽ cung cấp sự linh hoạt hơn cho người dùng. Để có hiệu ứng này, tôi sẽ trích dẫn việc di chuyển Ủy ban tiêu chuẩn được thực hiện với khái niệm Allocator: các nhà phân bổ trạng thái hiện được ủy quyền, cho chúng ta cơ hội đóng gói các nút của một trang map nhất định trong cùng một trang thay vì trải rộng trên tất cả các vùng.

Cuối cùng, có sự cố giao diện. Tuy nhiên nó đã được một thời gian dài kể từ khi Sutter ủng hộ rằng một lớp và các chức năng miễn phí được định nghĩa trong cùng một tiêu đề cả hai cấu thành giao diện công cộng của lớp này => đó là những gì ADL là dành cho! Vì vậy, nó là một cái gì đó để an ủi OO-lập trình viên cũ hơn là một "thực hành tốt".

Thực sự, tôi không thấy bất kỳ lợi ích nào khi sử dụng các hàm thành viên static. Tôi muốn mọi người sẽ nghĩ ngược lại để đề xuất những trường hợp thực sự.

Các vấn đề liên quan