2010-10-08 26 views
7

Tôi đã đọc các bài viết về các không gian tên không tên trong cả ngày, hầu hết các bài viết được giải thích khi bạn nên sử dụng các không gian tên không tên trên từ khóa tĩnh. Nhưng tôi vẫn còn lại với một câu hỏi lớn khi nào nó thích hợp để sử dụng tĩnh? Sau khi tất cả nó không hoàn toàn không được chấp nhận, những gì về tập tin tiêu đề với các chức năng tĩnh nên tôi đặt chúng vào không gian tên chưa đặt tên bây giờ?Khi nào là thích hợp để sử dụng tĩnh (trên các không gian tên chưa đặt tên) trong C++?

#ifndef HEADER_H 
#define HEADER_H 

static int func() { 
    ... 
} 

// versus: 

namespace { 
    int func() { 
    ... 
    } 
}; 

#endif // HEADER_H 

Hoặc các chức năng thành viên tĩnh thì sao?

Chúc mừng

+7

Dường như phản tác dụng để đặt các không gian tên tĩnh (hoặc không tên) trong các tệp tiêu đề. Nếu họ là tĩnh tại sao họ không chỉ trong tập tin nguồn? –

Trả lời

3

Không có lợi thế nào trong phạm vi không gian tên trên các không gian tên chưa được đặt tên mà tôi biết. Sử dụng các không gian tên không tên, như trong ví dụ trên. Thực tế trong ví dụ trên tôi không thể thấy tại sao không gian tên tĩnh hoặc không tên là cần thiết. Có thể nội tuyến? Và các hàm thành viên tĩnh không có gì để làm với static ở phạm vi không gian tên. Các hàm thành viên tĩnh (và các thành viên không có chức năng) vẫn hợp lệ.

+0

Trong ví dụ tĩnh là cần thiết để tránh các chức năng có liên kết bên ngoài. Vì nó sẽ được thực hiện trong mỗi mô-đun sử dụng tiêu đề, trình liên kết có thể phản đối nếu từ khóa tĩnh không có mặt. –

+0

@Alexander: Vâng, nội tuyến sẽ cho phép nhiều định nghĩa của hàm. Và theo ý kiến ​​của tôi là một sự thay thế vượt trội. Tuy nhiên, nếu "LIÊN KẾT NỘI BỘ" là chính xác những gì cần thiết, thì không gian tên không tên là tốt hơn nhiều, ít nhất là vì nó không bị phản đối. –

+4

'inline' cho phép nhiều định nghĩa * giống hệt nhau * của hàm. 'tĩnh' cho phép nhiều định nghĩa khác nhau, vì mỗi đơn vị dịch có chức năng riêng của nó với liên kết nội bộ, chúng chỉ xảy ra khi được gọi cùng tên. Vì vậy, nếu có điều gì đó trong định nghĩa 'func' phụ thuộc vào một số #defines (như' assert'), và bạn muốn nó hợp pháp để kết hợp các TU khác nhau bao gồm tiêu đề với các giá trị khác nhau trong #define, thì bạn cần có 'static' hoặc một không gian tên chưa được đặt tên. 'inline' sẽ không làm, chính thức, mặc dù trong thực tế nó có thể hoạt động. –

5

Các từ ngữ chính xác của tiêu chuẩn là:

Việc sử dụng các từ khóa static bị phản đối khi tuyên bố các đối tượng trong phạm vi không gian tên.

Chức năng trong tệp tiêu đề phải là inline thay vì static hoặc trong không gian tên chưa đặt tên. inline có nghĩa là bạn sẽ chỉ kết thúc với tối đa một bản sao của hàm trong chương trình của bạn, trong khi các phương pháp khác sẽ cung cấp cho bạn một bản sao riêng biệt từ mỗi tệp bao gồm tiêu đề. Cũng như sưng lên, điều này có thể cho hành vi không chính xác nếu hàm chứa dữ liệu tĩnh chức năng. (EDIT: trừ khi hàm được cho là có định nghĩa khác nhau trong các đơn vị biên dịch khác nhau, có lẽ do các macro tiền xử lý khác nhau được xác định trước khi bao gồm tệp tiêu đề. Trong trường hợp đó, cách tốt nhất là không bao gồm nó. để chôn nó trong một ngôi mộ không được đánh dấu với một cổ phần thông qua trái tim bất hạnh của nó.)

Đối tượng dữ liệu, ngoài hằng số, thường không được xác định trong tệp tiêu đề, chỉ khai báo extern.

Chức năng thành viên tĩnh là một loại cá khác nhau và bạn phải sử dụng static ở đó vì không có cách nào khác để khai báo chúng. Việc sử dụng đó không được chấp nhận vì nó không nằm trong phạm vi không gian tên.

CẬP NHẬT: C++ 11 đã loại bỏ việc không dùng nữa, vì vậy không còn lý do cụ thể nào để sử dụng các không gian tên chưa đặt tên trên static. Nhưng bạn vẫn không nên sử dụng hoặc trong một tập tin tiêu đề, trừ khi bạn đang làm một cái gì đó kỳ lạ.

+0

"Tất cả các đối tượng dữ liệu không được xác định trong tệp tiêu đề, chỉ được khai báo bên ngoài nếu chúng cần liên kết bên ngoài". Điều này là không chính xác. "Đối tượng dữ liệu", như bạn gọi cho chúng, có liên kết bên ngoài theo mặc định, trừ khi chúng là const. Vì vậy, extern là cần thiết để làm cho tuyên bố của họ chỉ là một tuyên bố và không phải là một định nghĩa, đó là mặc định. Tuy nhiên, nếu cả extern và initializer đều có mặt, nó là một định nghĩa. –

+0

Các đối tượng dữ liệu thường cần được xác định trong các tệp tiêu đề. Điều đó bao gồm các hằng số (là các đối tượng). Tôi đoán đó là lời khuyên tốt cho người mới sử dụng C++ để tránh việc xác định (thành viên lớp tĩnh) hằng số của các kiểu không tách rời trong các tệp tiêu đề. Nhiều lập trình viên có kinh nghiệm hơn có thể làm điều đó bằng cách sử dụng ví dụ: các hằng số templated lừa. Một thủ thuật như vậy là một hàm trả về một tham chiếu đến một hằng số tĩnh cục bộ. –

+0

@Armen, @Alf: vâng, lời khuyên của tôi về các đối tượng dữ liệu hơi đơn giản. Tôi sẽ nói lại nó. –

3

Trong tệp tiêu đề thường không có điểm nào trong việc chỉ định liên kết nội bộ hoặc sử dụng không gian tên ẩn danh.

Trong tệp triển khai được biên dịch riêng, bạn có thể sử dụng static hoặc không gian tên ẩn danh để tránh xung đột tên cấp liên kết hoặc mã khách hàng dựa vào chi tiết triển khai. Một không gian tên ẩn danh cho phép bạn có liên kết bên ngoài, được yêu cầu cho các tham số mẫu và nó cũng hỗ trợ các định nghĩa lớp. Nhưng cuối cùng nó chỉ là một câu hỏi về tính thiết thực và sở thích cá nhân, trên cơ sở từng trường hợp.

static cho hàm thành viên không có liên quan gì đến đặc tả liên kết. Tuy nhiên, hàm thành viên static có liên kết bên ngoài.

0

static có thể thích hợp hơn nếu bạn đang sử dụng một số công cụ. Nó cũng hoạt động tốt hơn một chút với chức năng thụt lề tự động trong hầu hết các trình soạn thảo văn bản. Đó là một chút buồn, khi bạn phải tránh sử dụng một cái gì đó hữu ích bởi vì nó không làm việc với các công cụ mà thực sự cần hỗ trợ nó, nhưng tôi hứa bạn sẽ vượt qua nó.

Một câu hỏi ví dụ mà đưa ra một số gợi ý của đau tiềm năng trong bộ phận gỡ lỗi:

Viewing namespaced global variables in Visual Studio debugger?

Bạn có thể sẽ không cần phải tìm kiếm rất khó để tìm thấy nhiều vấn đề, nhưng vấn đề debugger đã đủ để làm cho tôi hoàn toàn từ bỏ không gian tên, đến mức tối đa có thể, vì vậy tôi chưa bao giờ nhìn xa hơn nữa.

Đề xuất cá nhân của tôi là đối với mã sẽ có ít hơn mãi mãi, người ta cũng có thể đi với static. Có hiệu quả tương tự như một không gian tên không tên, nhưng, trung bình trên tất cả các công cụ, nó được hỗ trợ tốt hơn. Về lý thuyết, một ngày nào đó nó sẽ biến mất hoàn toàn, nhưng tôi vui mừng công khai thừa nhận rằng tôi chắc chắn rằng ngày đó sẽ không bao giờ thực sự đi qua. Và trong thời gian đó, bạn đang tiết kiệm cho mình một số cơn đau.

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