2011-01-16 35 views
8

Trong đoạn mã, tôi có thể truy cập biến thành viên riêng bên ngoài phạm vi lớp. Mặc dù điều này không bao giờ nên được thực hiện, tại sao nó được phép trong trường hợp này? Có thực tiễn không tốt để nhận biến riêng tư được trả lại bằng tham chiếu không?Tại sao tôi có thể phơi bày các thành viên riêng khi tôi trả lại một tham chiếu từ một hàm thành viên công cộng?

#include <iostream> 
#include <cstdlib> 

class foo 
{ 
    int x; 
    public: 
     foo(int a):x(a){} 
     int methodOne() { return x; } 
     int& methodTwo() { return x; } 
}; 

int main() 
{ 
    foo obj(10); 
    int& x = obj.methodTwo(); 
    x = 20;    // With this statement, modifying the state of obj::x 

    std::cout << obj.methodOne(); 
    getchar(); 
    return 0; 
} 

Và liên quan đến phương pháp này, loại trả lại truyền đạt là gì? Và cũng có khi nào tôi nên có loại trả về loại này?

int& methodTwo() { return x; } 

PS: Tôi xin lỗi nếu dòng chủ đề là mơ hồ. Ai đó có thể thay đổi nó thành nội dung có liên quan ở đây không. Cảm ơn.

Trả lời

15

private không có nghĩa là "bộ nhớ này chỉ có thể được sửa đổi bởi chức năng thành viên" - điều đó có nghĩa là "nỗ lực truy cập trực tiếp biến này sẽ dẫn đến lỗi biên dịch". Khi bạn phơi bày một tham chiếu đến đối tượng, bạn đã tiếp xúc với đối tượng một cách hiệu quả.

Thực tiễn không tốt để nhận biến riêng tư được trả về bằng tham chiếu?

Không, nó tùy thuộc vào thứ bạn muốn. Những thứ như std::vector<t>::operator[] sẽ khá khó thực hiện nếu chúng không thể trả về tham chiếu không phải là const :) Nếu bạn muốn trả lại tham chiếu và không muốn khách hàng có thể sửa đổi nó, chỉ cần đặt tham chiếu const.

+0

Đối với những người đi qua: [câu hỏi này] (http://stackoverflow.com/questions/8005514/is-returning-references-of-member-variables-bad-pratice) cho thấy có thể nguy hiểm khi trả lại một tham chiếu đến thành viên lớp học. – Arthur

+0

@Arthur: Vâng, như tôi đã nói, nó phụ thuộc vào những gì bạn muốn làm. Nó hoạt động tốt cho 'std :: vector' - nhưng có rất nhiều trường hợp mà nó là điều sai trái để làm quá. –

3

Trả lại thành viên riêng tư dưới dạng tham chiếu hoàn toàn hợp lệ và người lập trình viết lớp có trách nhiệm lựa chọn cẩn thận nếu điều này được cho phép. This link đưa ra một ví dụ khi điều này có thể được thực hiện.

2

Mã này:

int& methodTwo() { return x; } 

Có nghĩa là hàm trả về một tài liệu tham khảo đến một số nguyên. Cũng giống như khi chuyển một giá trị bằng cách tham chiếu đến một hàm, nếu giá trị trả về của methodTwo bị thay đổi, thì giá trị trả về là methodTwo. Trong trường hợp này, trường lớp x.

Trong mã bạn đã viết, điều này có nghĩa là bạn đang để biến riêng x thoát khỏi phạm vi của nó (một trường lớp) và được truyền xung quanh trong thế giới bên ngoài. Điều này chắc chắn là một thói quen xấu (vì x có thể thay đổi theo những cách mà có thể phá vỡ lớp foo, nhưng nó chắc chắn là cho phép.

Ghi public/private/bảo vệ được thời gian biên dịch chỉ. Một khi ứng dụng của bạn được biên soạn, Điều này cũng đúng đối với các ngôn ngữ được quản lý như C# và Java ..

Thông thường bạn nên tránh các tham chiếu trả về vì nó khó hiểu khi xây dựng/hủy Tuy nhiên, trả về một tham chiếu có thể nhanh hơn.Nếu phương thức của bạn trả về kiểu cấu trúc là HUGE, trả về tham chiếu const cho cùng một đường loại uct chỉ nên có bốn đến tám byte (một con trỏ đến đối tượng đó). Tuy nhiên, có những cách tốt hơn để tối ưu hóa cho loại điều này.

+1

Tôi mạnh mẽ không đồng ý với điểm "bạn nên tránh trả về tham chiếu" - do trình biên dịch tự do bỏ qua cuộc gọi đến hàm tạo bản sao nếu bạn trả về giá trị, điều duy nhất bạn đạt được trong nhiều trường hợp bằng cách quay lại giá trị là chậm xây dựng gỡ lỗi (vì trình biên dịch không RVO/NRVO về bạn trong chế độ phát hành). –

+1

Không phải là một người dùng C++ cấp độ guru, tôi bảo lưu quyền là sai :) Nhưng bạn sẽ không nhận được hành vi không xác định nếu bạn trả về một tham chiếu đến biến cục bộ? (Tức là, bạn được để lại với một con trỏ đến một số điểm ngẫu nhiên trên ngăn xếp?) –

+0

Đó là chính xác. Cố gắng truy cập một biến bị phá hủy thông qua kết quả tham chiếu trong hành vi không xác định. Nhưng đối với những thứ như getters lớp trở lại bằng cách tham chiếu là hành vi bình thường và mong đợi. –

0

Giống như Donotalo đã nói, nó hoàn toàn hợp lệ.Ý tưởng về việc có các thành viên riêng tư là không cho phép các lớp/chức năng khác truy cập thành viên riêng tư của lớp học mà không cần sự cho phép của bạn. Nếu bạn rất vui khi thực hiện một chức năng để cho phép các lớp/chức năng khác truy cập vào các thành viên riêng của bạn, trình biên dịch không có gì chống lại điều đó :-)

Thông thường, bạn có thể có một thành viên riêng và có nhận để cho phép các lớp/hàm khác có được giá trị của hàm, nhưng chỉ có lớp mới có thể thay đổi nó.

-1

Tôi có thể truy cập vào các biến thành viên tin ngoài phạm vi lớp

Nếu bạn đang đề cập đến x trong main() thì đó là khác biệt so với x khai báo trong class foo. Nếu bạn cố gắng truy cập vào obj.x thì trình biên dịch chắc chắn sẽ phàn nàn.

Thực tiễn không tốt để nhận biến riêng tư được trả về bằng tham chiếu?

Không có gì sai khi "nhận" tham chiếu đến thành viên riêng tư. Nhưng đưa ra các tham chiếu đến một thành viên tư nhân làm cho tuyên bố nó tư nhân vô dụng. Bằng cách khai báo một biến là một thành viên riêng, bạn hạn chế quyền truy cập vào thành viên đó chỉ với các phương thức của lớp.

liên quan đến phương pháp này, loại trả lại truyền đạt là gì? Và cũng có khi nào tôi nên có loại trả về loại này?

Bạn không biết chắc bạn đang đề cập đến phương pháp nào?!?!?!

+2

Thật sao? Nó làm cho nó vô ích? Làm thế nào để bạn giải thích 'std :: vector :: toán tử []' sau đó? Bất kỳ con trỏ đệm nào mà vectơ đang sử dụng không được tiếp xúc với thế giới, nhưng dữ liệu (và phải là, cho điểm của vectơ) –

+0

@Billy O'Neal: Điểm tốt. Cảm ơn đã chỉ ra điều đó. – yasouser

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