Tôi đã tìm thấy một vài câu hỏi khác dường như ngụ ý câu hỏi của tôi, nhưng không có câu hỏi nào trả lời trực tiếp câu hỏi đó (thậm chí the one có cùng tên).Tại sao upcasting một con trỏ đến một lớp cơ sở đôi khi thay đổi giá trị con trỏ?
Tôi có một lớp con C++ có nguồn gốc từ hai cha mẹ. Tôi tạo ra một đối tượng của lớp đó, sau đó đưa tham chiếu của nó đến từng cha mẹ của nó. Các giá trị truyền không giống nhau, mặc dù giá trị này vẫn là giá trị của tham chiếu con. Dưới đây là các mã:
class Mom
{
public:
int a = 1;
};
class Dad
{
public:
int b = 2;
};
class Child : public Mom, public Dad
{
public:
int c = 3;
};
int main()
{
Child* c = new Child; // 0x00C5A618
Mom* m = c; // 0x00C5A618
Dad* d = c; // 0x00C5A61C
return 0;
}
Bây giờ, tôi đoán rằng các địa chỉ thu được bằng cách áp dụng static_cast <> là của các subobjects thực tế. Khi điều đó xảy ra, Mom
là subobject đầu tiên, vì vậy nó thực sự có cùng địa chỉ là Child
. Dad
là subobject thứ hai, do đó, nó nằm ở một địa chỉ khác.
Theo tôi được biết, C-style phôi, như thế này
Mom* m = (Mom*)c;
Dad* d = (Dad*)c;
sẽ áp dụng một static_cast <> khi nó sẽ là pháp lý để làm như vậy. Thật vậy, khi tôi thực sự biên dịch và thực thi phiên bản đó, tôi thấy hành vi tương tự như trước đây.
Tiếp tục saga sắc sảo này, sử dụng phôi tiềm ẩn, như
Mom* m = c;
Dad* d = c;
triển lãm này hành vi tương tự là tốt, mà từ đó tôi suy ra rằng phôi ngầm cũng được áp dụng static_cast <> khi các diễn viên rõ ràng tương đương sẽ là hợp pháp.
downcasting trở lại Child
làm điều tương tự:
Child* k = static_cast<Child*>(d); // 0x00C5A618
Giá trị trong k
khác với giá trị trong d
, đã được thiết lập trở lại với giá trị ban đầu trong c
.
Tôi đoán rằng, trong trường hợp này, có kiểm tra thời gian chạy để xem liệu, thực sự, d
trỏ đến một đối tượng Dad
của đối tượng Child
.
Cho đến nay, tất cả đều có ý nghĩa, nhưng tôi ngạc nhiên rằng không có điều chỉnh địa chỉ như vậy (nếu đó là điều đúng để gọi nó) cho phân cấp đơn lẻ có nguồn gốc. Nghĩa là, nếu hệ thống cấp bậc của tôi chỉ đơn giản là Mom
->Dad
->Child
, đúc một tham chiếu đến một Child
thành một con trỏ đến hoặc là một Mom
hoặc một Dad
bao giờ thay đổi giá trị:
class Mom
{
public:
int a = 1;
};
class Dad : public Mom
{
public:
int b = 2;
};
class Child : public Dad
{
public:
int c = 3;
};
int main()
{
Child* c = new Child; // 0x00C5A618
Mom* m = c; // 0x00C5A618
Dad* d = c; // 0x00C5A618
Child* k = static_cast<Child*>(d); // 0x00C5A618
return 0;
}
tôi đã mong đợi nó để thay đổi kích thước của bộ nhớ cần thiết cho mỗi lớp con bổ sung hoặc bốn byte (kích thước của một int). Nhưng, họ thì không. Tất cả các con trỏ trong ví dụ trên, c
, m
, d
và k
, có cùng giá trị.
Vì vậy, bây giờ tôi đang đoán rằng các đối tượng đã được đặt ra trong bộ nhớ với các đối tượng Mom
tại địa chỉ thấp nhất, thêm không gian cần thiết cho đối tượng Dad
sắp tới, và thêm không gian cần thiết cho việc Child
đến cuối cùng. Kể từ số Dad
là-a Mom
, địa chỉ Dad
sẽ giống với địa chỉ Mom
, phải không?
Tương tự, một số Child
cũng là Mom
, vì vậy địa chỉ của địa chỉ cũng giống như địa chỉ của địa chỉ phụ của địa chỉ Mom
.
Vậy ...
Tôi nghĩ rằng nó đang làm việc như thế này: trong bộ nhớ, các đối tượng theo nhau như vậy mà, trong hoàn toàn đơn lẻ có nguồn gốc hệ thống phân cấp, upcasting và downcasting luôn mang lại cùng một địa chỉ, trong khi ở một nhân hệ thống phân cấp có nguồn gốc, một số upcasts mang lại một địa chỉ khác, bởi vì không phải tất cả các subobject sẽ bắt đầu tại cùng một địa chỉ với đối tượng dẫn xuất. Như thế này:
Possible Memory Layout for a Singly Derived Hierarchy
+-------+-----+-----+---+
| Child : Dad : Mom : a |
| | +-----+---+
| | : b |
| +-----------+---+
| : c |
+-----------------------+
Possible Memory Layout for a Multiply Derived Hierarchy
+-------+-----+---+
| Child : Mom : a |
| +-----+---+
| : Dad : b |
| +-----+---+
| : c |
+-----------------+
Xin lỗi mà tôi đã lan man một chút, nhưng câu hỏi của tôi là thế này: là một thực tế rằng một bị ném lên trời để một số lớp cơ sở của một đối tượng nhân có nguồn gốc thay đổi giá trị của các tài liệu tham khảo là kết quả của thực tế là giá trị sau khi truyền là địa chỉ của đối tượng cơ sở trong bộ nhớ?
Có ........... – Soren