1. Hàm inline (Hàm nội tuyến)
Khi chương trình gọi một hàm, sẽ có chi phí về thời gian và bộ nhớ cho việc chuyển luồng điều khiển. C++ cung cấp cơ chế hàm inline: trong quá trình biên dịch, mã của hàm inline được chèn trực tiếp vào nơi gọi thay vì thực hiện lệnh gọi hàm. Điều này giúp tiết kiệm thời gian cho các thao tác lưu/khôi phục ngữ cảnh.
#include <iostream>
using namespace std;
inline int timMax(int a, int b, int c);
int main() {
int x = 1, y = 2, z = 3;
int m = timMax(x, y, z);
cout << "Max = " << m << endl;
return 0;
}
inline int timMax(int a, int b, int c) {
if (b > a) a = b;
if (c > a) a = c;
return a;
}
Hàm inline làm tăng kích thước mã máy vì mã được nhân bản tại mỗi điểm gọi. Cần cân nhắc khi sử dụng cho các hàm dài hoặc được gọi nhiều lần.
2. Hàm thành viên (Member function)
Khi định nghĩa hàm thành viên bên ngoài lớp, phải dùng toán tử phạm vi :: để chỉ rõ hàm thuộc lớp nào.
#include <iostream>
#include <string>
using namespace std;
class HocSinh {
public:
void hienThi();
void nhap();
private:
int maSo;
char gioiTinh;
string hoTen;
};
void HocSinh::hienThi() {
cout << "Ma so: " << maSo << endl;
cout << "Gioi tinh: " << gioiTinh << endl;
cout << "Ho ten: " << hoTen << endl;
}
void HocSinh::nhap() {
cin >> maSo;
cin >> gioiTinh;
cin >> hoTen;
}
int main() {
HocSinh hs;
hs.nhap();
hs.hienThi();
return 0;
}
Các hàm định nghĩa bên ngoài lớp không tự động là inline, giúp tách biệt interface và implementation.
3. Constructor có tham số
Constructor có thể nhận tham số để khởi tạo các thuộc tính.
#include <iostream>
using namespace std;
class HinhHop {
private:
int chieuCao;
int chieuRong;
int chieuDai;
public:
HinhHop(int c, int r, int d); // Constructor
int theTich();
};
HinhHop::HinhHop(int c, int r, int d) {
chieuCao = c;
chieuRong = r;
chieuDai = d;
}
int HinhHop::theTich() {
return chieuCao * chieuRong * chieuDai;
}
int main() {
HinhHop hop1(12, 25, 10);
cout << "The tich hop1: " << hop1.theTich() << endl;
return 0;
}
Có thể sử dụng danh sách khởi tạo (initializer list) để viết gọn hơn:
class HinhHop {
private:
int chieuCao;
int chieuRong;
int chieuDai;
public:
HinhHop(int c, int r, int d) : chieuCao(c), chieuRong(r), chieuDai(d) {}
int theTich();
};
Nếu dữ liệu là mảng, phải gán trong thân constructor, không dùng danh sách khởi tạo được.
class SinhVien {
private:
int id;
char ten[20];
public:
SinhVien(int i, char t[]) : id(i) {
strcpy(ten, t);
}
void hienThi() {
cout << id << " " << ten << endl;
}
};
int main() {
SinhVien sv(1, "Nguyen Van A");
sv.hienThi();
return 0;
}
4. Nạp chồng Constructor (Constructor overloading)
Một lớp có thể có nhiều constructor với tham số khác nhau.
#include <iostream>
using namespace std;
class HinhHop {
private:
int chieuCao;
int chieuRong;
int chieuDai;
public:
HinhHop(); // Không tham số
HinhHop(int c, int r, int d) : chieuCao(c), chieuRong(r), chieuDai(d) {}
int theTich();
};
HinhHop::HinhHop() {
chieuCao = 10;
chieuRong = 10;
chieuDai = 10;
}
int HinhHop::theTich() {
return chieuCao * chieuRong * chieuDai;
}
int main() {
HinhHop hop1; // Gọi constructor không tham số
cout << "The tich hop1: " << hop1.theTich() << endl;
HinhHop hop2(12, 25, 10);
cout << "The tich hop2: " << hop2.theTich() << endl;
return 0;
}
Lưu ý: Khi tạo đối tượng với constructor không tham số, viết HinhHop hop1; chứ không phải HinhHop hop1(); vì dòng sau sẽ bị hiểu là khai báo hàm.
5. Constructor với tham số mặc định
Có thể đặt giá trị mặc định cho các tham số của constructor.
#include <iostream>
using namespace std;
class HinhHop {
private:
int chieuCao;
int chieuRong;
int chieuDai;
public:
HinhHop(int c = 10, int r = 10, int d = 10) : chieuCao(c), chieuRong(r), chieuDai(d) {}
int theTich() { return chieuCao * chieuRong * chieuDai; }
};
int main() {
HinhHop hop1; // 10x10x10
HinhHop hop2(12, 25); // 12x25x10
HinhHop hop3(12, 25, 30); // 12x25x30
cout << "The tich hop1: " << hop1.theTich() << endl;
cout << "The tich hop2: " << hop2.theTich() << endl;
cout << "The tich hop3: " << hop3.theTich() << endl;
return 0;
}
Không được định nghĩa đồng thời constructor mặc định và constructor có tham số mặc định vì sẽ gây nhập nhằng.
6. Destructor (Hàm hủy)
Destructor là hàm thành viên đặc biệt, tên bắt đầu bằng ~. Nó được gọi tự động khi đối tượng bị hủy, dùng để dọn dẹp tài nguyên. Destructor không có tham số, không trả về giá trị và không thể nạp chồng.
#include <iostream>
#include <string>
using namespace std;
class SinhVien {
private:
int maSo;
string hoTen;
char gioiTinh;
public:
SinhVien(int m, string ten, char gt) {
maSo = m;
hoTen = ten;
gioiTinh = gt;
cout << "Constructor " << maSo << " called!" << endl;
}
~SinhVien() {
cout << "Destructor " << maSo << " called!" << endl;
}
void hienThi() {
cout << "Ma so: " << maSo << endl;
cout << "Ho ten: " << hoTen << endl;
cout << "Gioi tinh: " << gioiTinh << endl;
}
};
int main() {
SinhVien sv1(1, "Nguyen Van B", 'm');
sv1.hienThi();
SinhVien sv2(2, "Test", 'f');
sv2.hienThi();
return 0;
}
Các đối tượng được hủy theo thứ tự ngược với thứ tự tạo (giống stack). Nếu khai báo biến static, nó chỉ bị hủy khi kết thúc chương trình.
7. Mảng đối tượng (Object array)
Có thể tạo mảng chứa các đối tượng của một lớp.
#include <iostream>
using namespace std;
class HinhHop {
private:
int chieuCao;
int chieuRong;
int chieuDai;
public:
HinhHop(int c = 10, int r = 10, int d = 10) : chieuCao(c), chieuRong(r), chieuDai(d) {}
int theTich() { return chieuCao * chieuRong * chieuDai; }
};
int main() {
HinhHop mang[4] = {
HinhHop(),
HinhHop(20),
HinhHop(10, 30),
HinhHop(10, 10, 40)
};
for (int i = 0; i < 4; i++) {
cout << "The tich hop " << i+1 << ": " << mang[i].theTich() << endl;
}
return 0;
}