2011-01-28 29 views
17

Tôi không thể nghĩ ra một từ ngữ tốt hơn cho tiêu đề, do đó, nó là một chút gây hiểu lầm, tuy nhiên, tôi không nói về một đứa trẻ truy cập vào các biến của nó được thừa hưởng từ cha mẹ của nó, đó là dễ dàng đủ.Truy cập vào các biến được bảo vệ của phụ huynh

Những gì tôi đang nói về là thế này:

class Parent { 
    protected: 
    Parent *target; 
    int hp; 
} 

class Child : public Parent { 
    public: 
    void my_func(); 
} 

void Child::my_func() { 
    target->hp -= 50; 
} 

Tuy nhiên, nếu tôi cố gắng biên dịch này, nó sẽ phàn nàn về 'hp' là "tư nhân trong bối cảnh này". Vấn đề là đứa trẻ không cố gắng truy cập vào các biến của cha mẹ riêng của nó, nhưng một số lớp khác ', mà có thể hoặc không thể là một Child.

Một đối tượng có thể truy cập tất cả các biến và phương thức (công khai, được bảo vệ hoặc riêng tư) của một đối tượng khác (hai trường hợp riêng biệt trong bộ nhớ) cùng một lớp, vì vậy tôi nghĩ rằng nó sẽ hoạt động với điều này, vì nó kế thừa từ lớp có các biến mà nó đang cố gắng truy cập, nhưng có vẻ như tôi đã sai khi giả sử như vậy.

Bất kỳ mẹo nào?

P.S. Không phải là thô lỗ hoặc bất cứ điều gì, nhưng tôi biết rằng tôi chỉ có thể tạo phương thức get() và set(), nhưng tôi đã hy vọng một cách rõ ràng hơn.

+0

Có rất nhiều lỗi trong mã của bạn như được viết ở đây (từ khóa được viết hoa không chính xác 'lớp', cú pháp thừa kế không chính xác, v.v.) mà tôi chắc chắn là lỗi chính tả không có trong mã gốc. Nó có thể hữu ích để có được một ví dụ tối thiểu mà không biên dịch được, sau đó sao chép và dán mã chính xác ở đây. –

+1

@Tim Tôi nghĩ rằng bạn đã có một cuộc trò chuyện với chính mình trong một phút ở đó, cho đến khi tôi so sánh hồ sơ –

+0

Vâng, tôi nên làm điều gì đó về điều đó. Nó không phải là duy nhất của một cái tên như tôi nghĩ. :-) –

Trả lời

22

hàm thành viên của một lớp học đặc biệt chỉ có quyền truy cập vào các thành viên protected của lớp cơ sở đó thực sự là subobjects lớp cơ sở của các đối tượng của kiểu lớp của mình (hoặc các loại có nguồn gốc hơn).

Thành viên của một lớp không có quyền truy cập vào thành viên được bảo vệ của các phiên bản khác của lớp cơ sở đó và cũng bị cấm truy cập vào các thành viên được bảo vệ thông qua tham chiếu hoặc con trỏ tới loại lớp cơ sở ngay cả khi thời gian chạy con trỏ hoặc tham chiếu là đối tượng thuộc loại lớp có chức năng thành viên đang cố gắng truy cập. Kiểm soát truy cập được thực thi tại thời gian biên dịch.

Ví dụ:

class X 
{ 
protected: 
    int z; 
}; 

class Y : X 
{ 
public: 
    int f(const Y& y) 
    { 
     return y.z; // OK 
    } 

    int g(const X& x) 
    { 
     return x.z; // Error, Y::g has no access to X::z 
    } 
}; 

Trong ví dụ của bạn, trong biểu thức target->hp, việc tiếp cận để target là hợp pháp bởi vì bạn đang truy cập vào một thành viên của đối tượng hiện hành (trong đó có các loại của lớp trong đó chức năng là thành viên, Child) nhưng quyền truy cập vào thành viên hp không hợp pháp vì loại target không phải là con trỏ đến Child, nhưng là con trỏ đến Parent.

+0

chapeau! Ví dụ tuyệt vời! –

+2

Có lẽ tôi đã không làm cho nó đủ rõ ràng trong OP, nhưng tôi hiểu điều đó. Tôi muốn biết nếu có bất kỳ cách nào tôi có thể làm điều này mà không có phương thức get() và set(). – Infiltrator

+0

@Tim: Câu trả lời của tôi đã cố gắng giúp giải thích giả định không chính xác của bạn. Có những hành vi lạm dụng nhưng bạn nên sửa hệ thống phân cấp lớp để bạn có quyền truy cập mà bạn cần. http://stackoverflow.com/questions/3364722/accessing-protected-member-of-template-parameter/3365221#3365221 –

-4

Cố gắng thay đổi để

Class Child : public Parent 
+1

Cùng một vấn đề xảy ra với thừa kế công khai. –

+1

Không có gì liên quan đến việc 'Child' thừa kế công khai hay riêng tư từ' Parent' hay không, đó là về phương thức 'Child' đang cố truy cập vào một thành viên được bảo vệ của' Parent' là một lớp con cơ sở của 'Child' hoặc một đó không phải là. –

+3

-1 không có gì liên quan đến vấn đề –

0

hmm này, lạ không ai nói ra điều đó cho đến nay, nhưng bạn có thể khai báo các trẻ em trở thành một người bạn của mẹ (có lẽ vì mã của bạn không phải là rất rõ ràng về những gì chính xác bạn muốn làm ở đây)

class Parent { 
    friend class Child; 
    protected: 
    int hp; 
} 

class Child { 
    public: 
    void my_func(); 
    Parent *target; 
} 

điều này sẽ cho phép truy cập. Hoặc bạn có thể viết một phương pháp accessor đó là công cộng:

class Parent { 
public: 
    get_hp(){return hp;} 
protected: 
    int hp; 
} 
+0

Có, tôi có thể làm điều đó, và đó là hack của tôi cho thời điểm này, nhưng nó chỉ có vẻ như nó phá vỡ "downwardness" của thừa kế. Bạn không cần phải kết bạn với mọi lớp học thừa hưởng từ nó để làm cho nó hoạt động. – Infiltrator

+0

Ngoài ra, như tôi đã nói, tôi biết rằng tôi chỉ có thể sử dụng phương thức set() và get(), về cơ bản là ví dụ của bạn. Tôi muốn xem nếu có bất kỳ cách nào để làm nó tương tự như cách tôi đang cố gắng và bạn sẽ có thể nếu bạn không sử dụng thừa kế. – Infiltrator

+0

@Tim: Như tôi đã nói trong bình luận của tôi với câu trả lời của Charles, vấn đề là bạn muốn phá vỡ sự trừu tượng được đại diện bởi lớp cơ sở. Bạn cần phải tự hỏi tại sao bạn muốn làm điều đó. – sbi

4

Điều này rất dễ (nghĩa là sự hiểu lầm rõ ràng của OP, là do mọi người không dành thời gian để đọc OP).

Bạn chỉ cần đặt con làm bạn của biến của cha mẹ mà bạn cần truy cập.

Hoặc, bạn có thể biến con thành bạn của lớp cha mẹ.

Bằng cách đó, mọi trẻ em đều có quyền truy cập vào các biến thành viên của bất kỳ phụ huynh nào, chính xác theo cách bạn mong đợi.

class Child; 

class Parent { 
    protected: 
    Parent *target; 
    int hp; 
    friend void Child::my_func(); 
} 

class Child : public Parent { 
    public: 
    void my_func(); 
} 

void Child::my_func() { 
    target->hp -= 50; 
} 

Nhược điểm của điều này là mọi trẻ đều có thể truy cập vào các biến của MỌI cha mẹ. Tuy nhiên, bạn phải xem xét rằng trong trường hợp của bạn, trình biên dịch không thể biết rằng mục tiêu Parent * là trường hợp giống như đứa trẻ. Cho rằng bạn đặt tên nó là mục tiêu, tôi hy vọng rằng có MỌI trẻ em có quyền truy cập vào các biến của MỌI cha mẹ là những gì bạn muốn.

Đây là một khả năng khác. Yêu cầu mọi người khác sử dụng giao diện để truy cập vào phụ huynh và chỉ có con của bạn sử dụng lớp cha mẹ thực sự. Kết quả là như nhau mặc dù. Mỗi đứa trẻ đều có quyền truy cập vào mọi biến của cha mẹ.

Bạn đang nhầm lẫn với lớp học. Trẻ có quyền truy cập vào cùng các biến thành viên của lớp cơ sở có cùng một INSTANCE.

+0

Bạn không thể biến một lớp thành một người bạn của một biến. Ý của bạn là nói "lớp" thay thế? – sbi

+0

Cũng lưu ý nhận xét của tôi cho Tim tại câu trả lời của Charles. Những gì tôi nói về 'bảo vệ' là tất cả sự thật về 'người bạn': Nó phá vỡ sự trừu tượng của một lớp học, kết nối chặt chẽ với bạn bè để thực hiện lớp học. Khớp nối chặt chẽ luôn luôn là xấu. Sử dụng 'friend' càng nhiều càng tốt, nhưng càng ít càng tốt. – sbi

+0

Sao chép-dán: Có, tôi có thể làm điều đó, và đó là hack của tôi cho thời điểm này, nhưng nó chỉ có vẻ như nó phá vỡ "downwardness" của thừa kế. Bạn không cần phải kết bạn với mọi lớp học thừa hưởng từ nó để làm cho nó hoạt động. – Infiltrator

Các vấn đề liên quan