2015-07-08 24 views
13

Tôi đang cố gắng để hiểu tại sao sau đây là một lỗi:Member chức năng với liên kết tĩnh

class Foobar { 
public: 
    static void do_something(); 
}; 

static void Foobar::do_something() {} // Error! 

int main() { 
    Foobar::do_something(); 
} 

lỗi này với "lỗi: không thể khai báo hàm thành viên 'static void Foobar :: do_something()' để có liên kết tĩnh "trong g + +, và" lỗi: 'tĩnh' chỉ có thể được xác định bên trong định nghĩa lớp "trong clang ++.

Tôi hiểu rằng cách khắc phục điều này là xóa "tĩnh" trong định nghĩa của do_something trên dòng 6. Tôi không hiểu, tại sao đây lại là vấn đề. Đó có phải là một lý do trần tục, chẳng hạn như "ngữ pháp C++ ra lệnh", hay là một cái gì đó phức tạp hơn đang xảy ra?

+0

Có thể trùng lặp với [Lỗi chức năng thành viên tĩnh; Cách viết đúng chữ ký?] (Https://stackoverflow.com/questions/8130066/static-member-functions-error-how-to-properly-write-the-signature) –

Trả lời

29

Tôi nghĩ vấn đề ở đây là từ khóa static có nhiều ý nghĩa khác nhau trong C++ và mã bạn đã viết ở trên sử dụng chúng theo hai cách khác nhau.

Trong ngữ cảnh hàm thành viên, static có nghĩa là "chức năng thành viên này không có đối tượng người nhận. Về cơ bản nó là hàm bình thường được lồng vào bên trong phạm vi của lớp."

Trong ngữ cảnh khai báo chức năng, static có nghĩa là "chức năng này chỉ được phạm vi cho tệp này và không thể được gọi từ những nơi khác".

Khi bạn thực hiện các chức năng bằng cách viết

static void Foobar::do_something() {} // Error! 

trình biên dịch hiểu các static đây có nghĩa là "Tôi đang thực hiện chức năng thành viên này, và tôi muốn thực hiện chức năng địa phương chỉ đến tập tin này." Điều đó không được phép trong C++ vì nó gây ra sự nhầm lẫn: nếu nhiều tệp khác nhau định nghĩa việc thực hiện chức năng thành viên của riêng chúng và sau đó khai báo chúng static để tránh va chạm khi liên kết, gọi cùng chức năng thành viên từ các vị trí khác nhau sẽ dẫn đến hành vi khác!

May mắn thay, khi bạn lưu ý, có một sửa chữa dễ dàng: chỉ cần xóa các từ khóa static từ định nghĩa:

void Foobar::do_something() {} // Should be good to go! 

Đây là hoàn toàn tốt đẹp bởi vì trình biên dịch đã biết rằng do_something là một chức năng static thành viên, vì bạn đã nói về điều đó trước đó.

Hy vọng điều này sẽ hữu ích!

+1

Điều đó có ý nghĩa, cảm ơn! Tôi cho rằng trình biên dịch có thể phân biệt giữa static void some_function() {...} và static void Foobar :: some_method() {...} và xử lý chúng một cách khác nhau, nhưng nó sẽ làm cho nó khó khăn hơn cho con người để phân tích vì hai ngữ nghĩa khác nhau và cú pháp rất giống nhau. Tôi không quá hài lòng với giải pháp, vì nó làm cho khó hơn để thấy rằng một phương pháp là tĩnh bằng cách nhìn vào việc thực hiện của nó (không có ý kiến), nhưng oh tốt. –

+0

Khi bạn sey 'Về cơ bản nó là một chức năng bình thường được lồng vào bên trong phạm vi của lớp 'bình thường bạn có nghĩa là toàn cầu? – TheLogicGuy

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