2012-11-29 33 views
6

Possible Duplicate:
C++: overriding public\private inheritancechức năng ảo tư nhân ở có nguồn gốc lớp

class base { 
public: 
    virtual void doSomething() = 0; 
}; 

class derived : public base { 
private: // <-- Note this is private 

    virtual void doSomething() 
    { cout << "Derived fn" << endl; } 
}; 

Bây giờ nếu tôi làm như sau:

base *b = new child; 
b->doSomething(); // Calls the derived class function even though that is private 

Câu hỏi:

  1. Nó có thể gọi hàm lớp có nguồn gốc mặc dù nó là riêng tư. Sao có thể như thế được?

Bây giờ nếu tôi thay đổi specifier truy cập thừa kế từ công chúng để bảo vệ/tin, tôi nhận được một lỗi biên dịch:

'type cast' : conversion from 'Derived *' to 'base *' exists, but is inaccessible 

Lưu ý: Tôi biết các khái niệm của specifiers truy cập thừa kế. Vì vậy, trong trường hợp thứ hai là nó có nguồn gốc tư nhân/bảo vệ, nó không thể tiếp cận. Nhưng tôi tự hỏi về câu trả lời cho câu hỏi đầu tiên. Bất kỳ đầu vào sẽ được đánh giá cao.

Trả lời

6

Kiểm soát truy cập được thực hiện tại thời gian biên dịch, không chạy theo thời gian, trong khi đa hình (bao gồm cả việc sử dụng các chức năng ảo) là một tính năng thời gian chạy.

+0

Tôi nghĩ rằng anh ấy muốn biết tại sao trình xác định truy cập hoạt động theo cách đó thay vì biết nguồn gốc của lỗi là gì. – Hossein

6

Trong trường hợp đầu tiên, kiểm tra truy cập được thực hiện (vì nó luôn được thực hiện) trên loại tĩnh mà cuộc gọi được thực hiện thông qua. Loại tĩnh của *bbase và trong trường hợp đó doSomething()public.

C++ 03 11.6 "Truy cập vào các chức năng ảo" nói:

The access rules (clause 11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it. [Example:

class B { 
public: 
    virtual int f(); 
}; 

class D : public B { 
private: 
    int f(); 
}; 

void f() 
{ 
    D d; 
    B* pb = &d; 
    D* pd = &d; 

    pb->f(); //OK:B::f()is public, 
      // D::f() is invoked 
    pd->f(); //error:D::f()is private 
} 

—end example]

Access is checked at the call point using the type of the expression used to denote the object for which the member function is called (B* in the example above). The access of the member function in the class in which it was defined (D in the example above) is in general not known.

Hãy ghi nhớ đặc biệt là "khả năng tiếp cận của hàm thành viên trong lớp, trong đó nó đã được xác định (D trong ví dụ trên) nói chung không được biết đến ". Nói chung, tại thời điểm trong ví dụ của bạn, trong đó b->doSomething(); được gọi, trình biên dịch có thể không có kiến ​​thức nào về số derived (hoặc child), ít hơn nhiều khả năng truy cập vào derived::doSomething() là riêng tư.

0

Chức năng riêng tư có nghĩa là bị ẩn khỏi thế giới bên ngoài và từ các lớp dẫn xuất. Mặc dù bạn đang ghi đè chỉ số truy cập của DoSomething của cha và làm cho nó riêng tư, bạn đang khởi tạo một lớp cơ sở; vì vậy trong trường hợp đầu tiên, bạn có thể gọi DoSomething của cơ sở vì nó là công khai. Kịch bản này có thể được sử dụng nếu bạn muốn ngăn mọi người bắt nguồn từ lớp dẫn xuất của bạn.

Trong trường hợp thứ hai, thông số truy cập private làm cho các thành viên của cơ sở không được tiếp xúc với người dùng của lớp dẫn xuất, điều này làm cho lớp dẫn xuất trở nên vô dụng.

+0

OP nói khá rõ ràng ** Có thể gọi hàm lớp dẫn xuất **. Suy đoán của bạn về ** bạn có thể gọi DoSomething của cơ sở vì nó là công khai ** là sai dựa trên ví dụ cho trước và không phải là câu trả lời cho câu hỏi 1. – StahlRat

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