Tôi đã cố gắng để gọi ::deletecho một lớp học trong operator deleteđó. Nhưng kẻ hủy diệt không được gọi.
Tôi định nghĩa một lớp MyClassmà operator deleteđã bị quá tải. Toàn cầu operator deletecũng quá tải. Các quá tải operator deletecủa MyClasssẽ gọi toàn cầu quá tải operator delete.
class MyClass
{
public:
MyClass() { printf("Constructing MyClass...\n"); }
virtual ~MyClass() { printf("Destroying MyClass...\n"); }
void* operator new(size_t size)
{
printf("Newing MyClass...\n");
void* p = ::new MyClass();
printf("End of newing MyClass...\n");
return p;
}
void operator delete(void* p)
{
printf("Deleting MyClass...\n");
::delete p; // Why is the destructor not called here?
printf("End of deleting MyClass...\n");
}
};
void* operator new(size_t size)
{
printf("Global newing...\n");
return malloc(size);
}
void operator delete(void* p)
{
printf("Global deleting...\n");
free(p);
}
int main(int argc, char** argv)
{
MyClass* myClass = new MyClass();
delete myClass;
return EXIT_SUCCESS;
}
Đầu ra là:
Newing MyClass...
Global newing...
Constructing MyClass...
End of newing MyClass...
Constructing MyClass...
Destroying MyClass...
Deleting MyClass...
Global deleting...
End of deleting MyClass...
Thực tế:
Chỉ có một cuộc gọi đến destructor trước khi gọi quá tải operator deletecủa MyClass.
Hy vọng:
Có hai cuộc gọi đến hàm hủy. Một trước khi gọi quá tải operator deletecủa MyClass. Khác trước khi gọi toàn cầu operator delete.
::delete p;gây ra hành vi không xác định do loại *pkhông giống với loại đối tượng bị xóa (cũng không phải là lớp cơ sở với hàm hủy ảo)
void*toán hạng thậm chí còn không rõ ràng. [expr.delete] / 1 : " Toán hạng sẽ là con trỏ tới loại đối tượng hoặc loại lớp. [...] Điều này ngụ ý rằng một đối tượng không thể bị xóa bằng cách sử dụng một con trỏ có kiểu void vì void không phải là một loại đối tượng. * "@OP Tôi đã sửa đổi câu trả lời của mình.
MyClass::operator new()nên phân bổ bộ nhớ thô, của (ít nhất)sizebyte. Nó không nên cố gắng xây dựng hoàn toàn một thể hiện củaMyClass. Các constructor củaMyClassđược thực hiện sauMyClass::operator new(). Sau đó,deletebiểu thức trongmain()gọi hàm hủy và giải phóng bộ nhớ (không gọi lại hàm hủy). Các::delete pbiểu hiện không có thông tin về loại đối tượngpđiểm vào, vìplà mộtvoid *, vì vậy không thể gọi destructor.