Tìm hiểu nội tại (internals) của Class trong C++. Trước đó, xem Constructor mặc định (default constructor) - constructor không nhận tham số.
Tại sao cần default constructor? Nếu không cung cấp, trình biên dịch sẽ ngầm khai báo default constructor. Default constructor dùng để khởi tạo các nội tại của class (v-table, vptr, base class subobjects), không ảnh hưởng đến data member do người dùng định nghĩa.
Trình biên dịch chèn gọi default constructor trong các trường hợp: - Class kế thừa từ base class có default constructor. - Class chứa object của class khác có default constructor.
Code minh họa
#include <iostream>
using namespace std;
class Base {
public:
// Trình biên dịch tạo default constructor cho Base
};
class ClassA {
public:
ClassA() {
cout << "ClassA Constructor (user-defined)" << endl;
}
int x; // Không được khởi tạo
};
class ClassB : public ClassA {
// Trình biên dịch tạo ClassB constructor
// Tự động chèn gọi ClassA constructor
};
class ClassC : public ClassA {
public:
ClassC() {
// User-defined, nhưng trình biên dịch vẫn chèn gọi ClassA()
cout << "User-defined ClassC Constructor" << endl;
}
};
class ClassD {
public:
ClassD() {
// User-defined, trình biên dịch chèn gọi ClassA constructor cho obj
cout << "User-defined ClassD Constructor" << endl;
}
private:
ClassA obj; // Object member
};
int main() {
Base baseObj; // Gọi Base::Base() (compiler-generated)
ClassB b; // Gọi ClassA::ClassA() -> ClassB::ClassB()
ClassC c; // Gọi ClassA::ClassA() -> ClassC::ClassC()
ClassD d; // Gọi ClassA::ClassA() -> ClassD::ClassD()
}
Kết quả
ClassA Constructor (user-defined) ClassA Constructor (user-defined) User-defined ClassC Constructor ClassA Constructor (user-defined) User-defined ClassD Constructor
Phân tích
Base baseObj: Gọi default constructor do compiler tạo (không in gì).ClassB b: ClassB không có constructor → compiler tạo, chèn gọi ClassA(). In "ClassA Constructor".ClassC c: ClassC có constructor → compiler chèn gọi ClassA() TRƯỚC thân hàm ClassC(). In ClassA trước, sau đó ClassC.ClassD d: ClassD có member ClassA obj → compiler chèn gọi ClassA() trong initializer list (trước thân ClassD). In ClassA trước, sau đó ClassD.
Quy tắc khởi tạo
- Base class constructor (theo thứ tự khai thừa).
- Member object constructor (theo thứ tự khai báo trong class).
- Constructor body của class hiện tại.
Hủyructor (destructor) chạy theo thứ tự ngược lại.