Những câu trả lời khác giải thích lý do đằng sau việc ngăn chặn đối tượng B
của bạn từ truy cập các bộ phận được bảo vệ của A
trong ví dụ của bạn, mặc dù B
'là-a' A
. Tất nhiên, cách dễ nhất để khắc phục sự cố này là làm cho các phần của A you want access to
công khai` hoặc có phương thức truy cập công khai có thể truy cập.
Tuy nhiên bạn có thể quyết định điều đó không phù hợp (hoặc bạn có thể không có quyền kiểm soát định nghĩa của A
). Dưới đây là một số gợi ý để cho phép bạn giải quyết vấn đề, theo thứ tự tăng dần kiểm soát truy cập của điều khiển truy cập. Lưu ý rằng tất cả các cách giải quyết này giả định rằng class A
có thể sao chép được.
Trong trường hợp đầu tiên, bạn chỉ cần sử dụng các nhà xây dựng bản sao cho A
để thiết lập một trạng thái ban đầu cho rằng một phần của đối tượng B
, sau đó sửa chữa nó lên sau đó:
class B1 : public A
{
public:
B1() : A(), z(0) {}
B1(const A& item) : A(item), z(1) {
// fix up the A sub-object that was copy constructed
// not quite the way we wanted
x = y;
y = 0;
}
private:
int z;
};
Tôi thấy rằng vô cùng khó hiểu và có lẽ rất dễ bị lỗi (giả sử rằng chúng ta muốn đối tượng phụ A
trong đối tượng B
khác với đối tượng A
được truyền cho hàm tạo - một tình huống bất thường, nhưng đó là điều được đưa ra trong vấn đề).Tuy nhiên, thực tế là nó có thể được thực hiện cho một số biện minh cho các ví dụ lật đổ hơn mà theo sau ...
Ví dụ tiếp theo tạo đối tượng B
tạm thời có bản sao chính xác đối tượng A
mà chúng tôi muốn truy cập. Sau đó chúng tôi có thể sử dụng đối tượng tạm thời B
để có được các mục được bảo vệ:
class B2 : public A
{
public:
B2() : A(), z(0) {}
B2(const A& item) : A(), z(1) {
// create a special-use B2 object that can get to the
// parts of the A object we want access to
B2 tmp(item, internal_use_only);
x = tmp.y; // OK since tmp is of type B
}
private:
int z;
// create a type that only B2 can use as a
// 'marker' to call a special constructor
// whose only purpose in life is to create
// a B object with an exact copy of another
// A sub-object in it
enum internal_use {
internal_use_only
};
B2(const A& item, internal_use marker) : A(item), z(0) {};
};
tôi tìm giải pháp mà là một chút ít khó hiểu hơn là người đầu tiên, nhưng nó vẫn còn khó hiểu (theo ý kiến của tôi). Có một phiên bản bastard của đối tượng B chỉ để đến các phần của đối tượng A mà chúng ta muốn là lẻ.
Chúng tôi có thể làm điều gì đó về điều đó bằng cách tạo một proxy đặc biệt cho A
các đối tượng cung cấp quyền truy cập mà chúng tôi muốn. Lưu ý rằng đây là giải pháp 'lật đổ nhiều nhất' vì đó là điều mà bất kỳ lớp nào cũng có thể thực hiện để truy cập vào các phần được bảo vệ của A
, ngay cả khi chúng không phải là các lớp con của chính bản thân họ là A
. Trong trường hợp của lớp B
, có một số tính hợp pháp để truy cập các bộ phận được bảo vệ của A
đối tượng, vì B
là một A
và như chúng tôi đã thấy có cách giải quyết khác cho phép chúng tôi có quyền truy cập chỉ sử dụng các quyền đó class B
có, vì vậy tôi xem xét điều này một phiên bản sạch hơn của những cách giải quyết trong trường hợp của class B
.
class B3 : public A
{
public:
B3() : A(), z(0) {}
B3(const A& item) : A(), z(1) {
// a special proxy for A objects that lets us
// get to the parts of A we're interested in
A_proxy tmp(item);
x = tmp.get_y();
}
private:
int z;
class A_proxy : public A
{
public:
A_proxy(const A& other) : A(other) {};
int get_x() {return x;};
int get_y() {return y;};
};
};
có lẽ, bạn đã quên 'ảo'? –
Pavel: oops, yeah, tôi đã thêm từ khóa 'virtual' ... nó không thực sự thay đổi quan điểm của tôi, mặc dù :) –