Sơ đồ các lớp trong iostream như sau:
• ios: là lớp cơ sở
• istream, ostream: là lớp kết thừa từ lớp ios • ifstream: là lớp kế thừa từ istream (và ios) • ofstream kế thừa từ ostream (và ios)
• iostream kế thừa từ istream và ostream (và ios) • fstream kế thừa từ ifstream, iostream, và ofstream
Trong chương 2, việc khai báo sử dụng đối tượng std::ofstream ta có thể dễ dàng sử dụng tốn tử << để ghi dữ liệu vào file dễ dàng như sử dụng std::cout khi xuất dữ liệu ra màn hình:
std::ofstream fout("myfile.dat"); int x = 10;
if (fout.good()) { // Make sure the file was opened properly
fout << "x = " << x << '\n'; }
Tài liệu giảng dạy Kỹ Thuật Lập Trình 2 Trang 87
std::cout << "Unable to write to the file
\"myfile.dat\"\n";
Ta đã biết, opperator<< có thể được nạp chồng (overload) trên vector như trong ví dụ sau:
ostream& operator<<(ostream& os, const std::vector<int>& vec) {
os << '{';
int n = vec.size(); if (n > 0)
{
// Is the vector non-empty?
os << vec[0]; // Send first element to the strean
for (int i = 1; i < n; i++) os << ',' << vec[i]; }
os << '}'; return os; }
Ta có thể dễ dàng điều chỉnh tốn tử << để có thể sử dụng nó như các đối tượng std::ofstream không?
Câu trả lời là ta khơng cần phải điều chỉnh tốn tử << mà nó vẫn có thể hoạt động tốt như các đối tượng std::ofstream. Nhờ có đối tượng std::cout có kiểu std::ostream khơng cùng lớp với std::ofstream.
C++ cho phép chuyển dễ dàng giữa những kiểu dữ liệu số học như int sang double hoặc ngược lại, kiểu int và bool được chuyển đổi tự động một cách liên tục. Các kiểu dữ liệu này được xây dựng sẵn do đó tiêu chuẩn chuyển đổi được áp dụng. Đối với kiểu dữ liệu do người dùng tự định nghĩa, trình biên dịch khơng thể tự tạo mã tùy ý để chuyển đổi từ kiểu dữ liệu này sang kiểu dữ liệu khác. Vì vậy làm thế nào đối tượng std::ofstream có thể tự động chuyển sang ostream. Ta có thể cho rằng vì cả hai đều là thành phần thuộc thư viện chuẩn của C++ do đó việc chuyển đổi được thực hiện. Thực tế là khơng có việc chuyển đổi xảy ra. Bất kỳ một đói tượng std::ofstream được tự động xử lý như một đối tượng ostream là vì giữa ostream và std::ofstream có mối liên hệ đặc biệt với nhau. std::ofstream là lớp dẫn xuất từ lớp ostream. Ta nói lớp ostream là lớp cơ sở (base class) và std::ofstream là lớp dẫn xuất (derived class). Các khác có thể gọi là lớp cha (superclass) và lớp con (subclass).
Tài liệu giảng dạy Kỹ Thuật Lập Trình 2 Trang 88
Base clase và derived class tự động hoán chuyển cho nhau mặc dù cộng đồng C++ thường gọi là lớp cha và lớp con. Qúa trình này được gọi là kế thừa (inheritance) bởi vì lớp dẫn xuất thừa hưởng những đặc tính từ lớp cơ sở. Các thuật ngữ “Derived”, “classes and specializations” cũng được dùng thay thế cho thuật ngữ “inheritance”
Theo quá trình kế thừa, một instance của một derived class được xử lý như một instance của một base class. Quan sát ví dụ sau:
//printstream.cpp
#include <fstream>
void print(std::ostream& os, int n) {
os.width(10); // Right justified in 10 spaces os.fill('*'); // Fill character is *
os << n << '\n'; }
int main() {
// Pretty print to screen print(std::cout, 35);
// Pretty print to text file std::ofstream fout("temp.data"); if (fout.good()) {
print(fout, 36); }
}
Trong ví dụ trên người dùng truyền tham số đầu tiên kiểu std::ostream cho hàm print nhưng khi sử dụng trong main thì cả hai ostream và ofstream đều được truyền cho hàm print. Khả năng này cho phép đối tượng lớp đẫn xuất được sử dụng trong bất kỳ ngữ cảnh nào của lớp cơ sở theo nguyên lý Likkov: “Trong
một chương trình, các đối tượng của lớp con có thể thay thế lớp cha mà không làm thay đổi tính đúng đắn của chương trình”. Cụ thể như sau:
Giả sử ta có lớp B và lớp D là lớp dẫn xuất từ lớp B. Khi đo B được gọi là base class và D được gọi là derived class. Ta có thể xử lý các instance của derived class giống như các instance của base class. Nếu ta khai báo một object của D: D d; // d là một object của D
Thì ta có thể nói d là D hay d là B.
#include<iostream>: chỉ thị này bao gồm các header<ios>, <istream>, <ostream> and <streambuf. Vì vậy, hầu hết chương trình cần <iostream> header cho các I/O operations. Bao gồm các standard stream objects sau:
Tài liệu giảng dạy Kỹ Thuật Lập Trình 2 Trang 89
cin: là objects thuộc istream class cho bàn phím.
cout là objects thuộc ostream class dùng cho luồng xuất chuẩn mặc định là màn
hình console.
Cerr và clog: là object thuộc ostream class sử dụng cho dịng thơng báo lỗi chuẩn
mặc định là hiển thị trên màn hình console.