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é tập Code viết 22:30 ngày 30/09/2018

Oh bạn overloading <<>> thì không thể dùng member function được mà phải dùng non-member function nhé vì <<>> là stream operator.

Trần Thị Diệu Ninh viết 22:32 ngày 30/09/2018

giải thích cụ thể cho e được k ạ? e mới tự học nên chưa rõ ạ

Bé tập Code viết 22:38 ngày 30/09/2018

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.

viết 22:40 ngày 30/09/2018

nói chính xác hơn là <<>> 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.

<<>> 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ệnh std::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ặc const T* nếu thêm const 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.

<< là operator cho stream nên vế trái của nó ở đây là std::ostream chứ ko phải PhanSo, 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 keyword friend 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áo friend <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 )

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ài friend.

Bé tập Code viết 22:36 ngày 30/09/2018

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.

viết 22:35 ngày 30/09/2018

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.

Bé tập Code viết 22:25 ngày 30/09/2018

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.

viết 22:32 ngày 30/09/2018

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.

Bé tập Code viết 22:36 ngày 30/09/2018

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ủa friend 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

Mai Anh Dũng viết 22:40 ngày 30/09/2018

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

Bé tập Code viết 22:40 ngày 30/09/2018

Chính xác, C++ chưa bao giờ “chỉ là ngôn ngữ hướng đối tượng” cả

Ngọc Trần viết 22:39 ngày 30/09/2018

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 ạ

Dark.Hades viết 22:38 ngày 30/09/2018

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

Ngọc Trần viết 22:33 ngày 30/09/2018

Cái friend nó cũng khai báo trong class mà anh/chị.

Bài liên quan
0