30/09/2018, 20:24
Thắc mắc nạp chồng toán tử input/output c++
Giả sử có 1 lớp phân số. khi nạp chồng operator <<, >> thì hầu như đều sử dụng hàm friend (2 đối số):
friend ostream& operator<<( ostream& os,phanso &ps);
friend istream& operator>>( istream& is,phanso &ps);
Nhưng e thắc mắc là nếu ta không dùng hàm bạn thì có được không? Nếu k dùng hàm bạn thì phải viết như thế nào ạ? Ai giúp e với
Bài liên quan
Oh bạn overloading
<<
và>>
thì không thể dùngmember function
được mà phải dùngnon-member function
nhé vì<<
và>>
là stream operator.giải thích cụ thể cho e được k ạ? e mới tự học nên chưa rõ ạ
huhm, chắc bạn đang học C++ và học tới bài
friend
nên có ví dụ này đúng không. Bạn tự code (và tìm hiểu) rồi thắc mắc chỗ nào đưa lên cụ thể, mình sẽ giải thích rõ hơn.nói chính xác hơn là
<<
và>>
là toán tử dịch bit. Lão Stroustrup bị khùng nên lấy toán tử dịch bit đi làm input output cho stream.<<
và>>
thì cũng như phép+
hay-
, có 2 phần tử tham gia: vế trái và vế phải. Viết 1 hàm cho toán tử có thể viết theo công thức<kiểu trả về> operator<toán tử>(<kiểu vế trái> <vế trái>, <kiểu vế phải> <vế phải>);
ví dụ
std::ostream& operator<<(std::ostream& out, const PhanSo& rhs);
thì kiểu trả về là
std::ostream&
toán tử là
<<
kiểu vế trái là
std::ostream&
(trùng với kiểu trả về)kiểu vế phải là
const PhanSo&
thì khi sử dụng
<<
trong câu lệnhstd::cout << ps;
vế trái làstd::cout
có kiểu kế thừa từstd::ostream
nên có thể xem làstd::ostream
, vế phải làps
có kiểu làPhanSo
được truyền const-reference vào<<
tức là truyền đích thịps
chứ ko tạo ra bản copy, vào bản chính truyền vào được xem như là 1 hằng.vì sao kiểu trả về trùng với kiểu vế trái: để có thể viết như vầy:
std::cout << ps1 << "\n";
Toán tử<<
được xét từ trái sang phải, tức làstd::cout << ps1 << "\n";
được xét(std::cout << ps1) << "\n";
Như vậy kết quả trả về của(std::cout << ps1)
sẽ là vế trái của toán tử<<
tiếp theo, vì vậy nên trả về trùng kiểu vế trái của toán tử trước nó.phương thức (hàm của class) thì vế trái luôn luôn có kiểu là
T*
(T là tên của class) hoặcconst T*
nếu thêmconst
vào phía sau khai báo của phương thức. Tức là con trỏthis
luôn được xem là vế trái của 1 phương thức trong class.vì
<<
là operator cho stream nên vế trái của nó ở đây làstd::ostream
chứ ko phảiPhanSo
, vì vậy phải viết hàm ko thuộc class. (hàm thuộc class gọi là phương thức, hàm ko thuộc class nào gọi là… hàm). Nhưng vì hàm nằm ngoài class ko thể truy cập các phần tửprivate
của class (ở đây là tử số và mẫu số) nên lão Stroustrup chế ra cái keywordfriend
tức là hàm này có quyền truy cập các phần tửprivate
của class thoải mái, miễn là có khai báofriend <khai báo hàm>
trong class (bạn bè có quyền lục lọi đồ riêng tư của bạn bè? Chọn tên cũng khùng vãi )vì
friend
đơn giản là phá hủy tính đóng gói (encapsulation), 1 trong các quy tắc của OOP, nên hạn chế xàifriend
.Không liên qua đến toán tử shift bit bạn nhé, dù cho nó có giống nhau về mặt hình thức. Cái này là kế thừa từ toán tử in/out của Unix.
friend
không phá hủy tính đóng gói,friend
nâng cấp tính đóng gói.phá hủy đó. Đóng gói tức là hiding data, tức là che dữ liệu lại bằng private hay protected, friend nó lờ đi hết 2 thứ đó thì phá hủy chứ nâng cấp gì ở đây.
Encapsulation không phải là Hiding Data, đừng đánh đồng.
Bạn đang đứng ở view Friend không thuộc class. Friend phải được coi là một phần của class, giúp mở rộng phạm vi của interface của class ra nên nó nâng cấp sự Encapsulation chứ không phải phá hủy.
Java, C# đâu có
friend
đâu, C++ đã làm class rồi lại thích trở về C struct nên mới có cái vụ friend này. OOP nói chung chả cần khái niệm friend làm gì. C++ thì nổi tiếng thích ôm đồm nhiều thứ nên mới có cái rắc rối như vậy.Về việc James Gosling không thêm keyword
friend
vào Java thì mình không đủ tư cách để phán xét. Nhưng rất nhiều trường hợp người viết Java phải hiện thực code theo hình thái củafriend
vì thấy nó hữu dụng, chẳng hạn trong Unit Testing.Việc thêm
friend
trong C++ hoàn toàn không liên quan đến C struct. C++ và C là hai ngôn ngữ riêng rẽ.C++ ôm đồm hay không thì mình cũng không dám phán xét luôn
Về vấn đề ôm đồm thì Đạt cùng ý kiến với @tntxtnt, C++ ôm đồm nhiều thứ quá. C++ không phải “chỉ là” hướng đối tượng
Why C++ is not just an Object-Oriented Programming Language
Chính xác, C++ chưa bao giờ “chỉ là ngôn ngữ hướng đối tượng” cả
Em vẫn còn một thắc mắc là friend có tác dụng giúp hàm truy cập các phần tử private nhưng mà theo em đã biết thì những hàm trong public thuộc class đó vẫn truy cập được phần tử private mà. Em mới học class được 3 ngày. Mong các anh chỉ giáo ạ
Hàm thuộc class đó nó vẫn nằm trong class đó, những gì bên ngoài mới không tác động được, kể cả class con
Protected thì class con có thể tác động được.
Bạn nên học lại khái niệm về 3 thằng public/protected/private
Cái friend nó cũng khai báo trong class mà anh/chị.