A a = *(A *)new B();
a.func();
Đây là những gì xảy ra trong mã này, từng bước:
new B()
: đối tượng mới loại B được phân bổ trên cửa hàng miễn phí, dẫn đến địa chỉ
(A*)
: địa chỉ của đối tượng được đúc thành A*
, vì vậy chúng tôi trỏ đến một đối tượng thuộc loại B, hợp lệ. Tất cả ok.
A a
: tại đây sự cố bắt đầu. Một đối tượng địa phương mới loại A được tạo trên ngăn xếp và được tạo bằng cách sử dụng hàm tạo bản sao A::A(const A&)
, với đối tượng đầu tiên là đối tượng được tạo trước đó.
- Con trỏ đến đối tượng gốc loại B bị mất sau tuyên bố này, dẫn đến rò rỉ bộ nhớ, vì nó được cấp phát trên cửa hàng miễn phí với
new
.
a.func()
- phương pháp được gọi trên đối tượng (địa phương) của lớp A.
Nếu bạn thay đổi mã để:
A& a = *(A*) new B();
a.func();
sau đó chỉ có một đối tượng sẽ được xây dựng, con trỏ của nó sẽ được chuyển đổi sang con trỏ kiểu A*
, sau đó dereferenced và tham chiếu mới sẽ được khởi tạo với địa chỉ này. Cuộc gọi của hàm ảo sau đó sẽ được giải quyết động theo số B::func()
.
Nhưng hãy nhớ, bạn vẫn sẽ cần phải giải phóng các đối tượng vì nó đã được phân bổ với new
:
delete &a;
Trong đó, bằng cách này, chỉ sẽ được chính xác nếu A có một destructor ảo , đó là yêu cầu mà B :: ~ B() (may mắn là có sản phẩm nào ở đây, nhưng nó không cần phải trong trường hợp chung) cũng sẽ được gọi. Nếu A không có một destructor ảo, sau đó bạn sẽ cần phải giải phóng nó bằng cách:
delete (B*)&a;
Nếu bạn muốn sử dụng một con trỏ, thì đó là giống như với các tài liệu tham khảo. Mã số:
A* a = new B(); // actually you don't need an explicit cast here.
a->func();
delete (B*)a; // or just delete a; if A has a virtual destructor.
Khi lỗi cú pháp được cố định sao cho nó biên dịch, mã của bạn làm điều đúng (gọi 'B :: func()'). Vì đây không phải là mã * thực * của bạn, tôi không biết vấn đề của bạn có thể là gì! –
Mã này không biên dịch (ít nhất là đối với tôi). Visual C++ 2008 Express – mnn
@mnm: Ah, tôi thấy bạn đã thay đổi nó. Trên thực tế, nó vẫn không biên dịch (thiếu ';' ở cuối mỗi định nghĩa lớp). –