Gọi hàm ảo từ constructor (hoặc destructor) là nguy hiểm và nên tránh. Khi constructor của lớp cơ sở chạy, đối tượng chưa hoàn toàn trở thành lớp dẫn xuất – vtable vẫn trỏ đến hàm ảo của lớp cơ sở. Do đó hàm ảo của lớp cơ sở được gọi, không phải của lớp dẫn xuất.
Ví dụ
#include <iostream>
using namespace std;
class Base {
public:
Base() { f(); } // Gọi ảo trong constructor
virtual void f() { cout << "Base\n"; }
};
class Derived : public Base {
public:
Derived() : Base() {}
void f() override { cout << "Derived\n"; }
};
int main() {
Derived d; // In "Base", không phải "Derived"
return 0;
}
Kết quả
Base
Nguyên nhân: C++ xây dựng lớp cơ sở trước lớp dẫn xuất. Khi Base::Base() chạy, phần Derived chưa tồn tại, vtable chưa cập nhật.