2010-01-28 31 views
15

Thật dễ dàng để hiểu chức năng ảo trong thừa kế công khai. Vì vậy, điểm cho chức năng ảo trong kế thừa riêng tư hoặc bảo vệ là gì?chức năng ảo trong kế thừa riêng hoặc được bảo vệ

Ví dụ:

class Base { 
public: 
virtual void f() { cout<<"Base::f()"<<endl;} 
}; 

class Derived: private Base { 
public: 

void f() { cout<<"Derived::f()"<<endl;} 

}; 

là vẫn được gọi là trọng này? Việc sử dụng trường hợp này là gì? Mối quan hệ của hai f() là gì?

Cảm ơn!

Trả lời

11

cá nhân thừa kế chỉ là một kỹ thuật thực hiện, không phải là một là-một mối quan hệ, như Scott Meyers giải thích trong Effective C++:

class Timer { 
public: 
    explicit Timer(int tickFrequency); 
    virtual void onTick() const; // automatically called for each tick 
    ... 
}; 

class Widget: private Timer { 
private: 
    virtual void onTick() const; // look at Widget private data 
    ... 
}; 

Widget khách hàng không nên có thể gọi onTick trên Widget, bởi vì đó là không phải là một phần của giao diện Widget khái niệm.

+0

Đó là một ví dụ điển hình khác. – Omnifarious

+0

Trên thực tế, đó chỉ là một ví dụ điển hình. Tôi trả lời câu hỏi sai. Rất tiếc. :-) – Omnifarious

1
  • Không cần phải là điểm cho mọi kết hợp các tính năng khác nhau. Bạn chỉ được phép kết hợp chúng.
  • Một thành viên được bảo vệ ảo có thể truy cập vào các lớp dẫn xuất, vì vậy nó rất hữu ích cho họ.
  • Một thành viên riêng tư ảo có thể truy cập được vào các lớp bạn bè, vì vậy nó hữu ích cho họ.
1

Một ví dụ sẽ là:

/// Thread body interface 
class runnable 
{ 
public: 

    virtual ~runnable() {} 
    virtual void run() =0; 
}; 

/// Starts OS thread, calls p->run() in new thread 
thread_id start_thread(runnable* p); 

/// Has a private thread 
class actor: private runnable, private noncopyable 
{ 
private: 

    thread_id tid; /// private thread 

public: 

    actor() { tid = start_thread(this); } // here this IS-A runnable 
    // ... 
    virtual ~actor() { stop_thread(tid); } 

private: 

    virtual void run() { /* work */ } 
}; 
+0

-1: ví dụ này * thực sự * cần hiển thị ai gọi 'run()' – Potatoswatter

+0

Hàm start_thread() tất nhiên. –

+0

Nhưng nó gọi là 'chạy' như thế nào?Đó là riêng tư. –

1

Cả hai thừa kế private và protected cho phép chức năng ảo trọng trong lớp cơ sở tư nhân/bảo vệ và không tuyên bố sự có nguồn gốc là một loại của cơ sở của nó.

Bảo vệ thừa kế cho phép các lớp dẫn xuất của các lớp dẫn xuất để biết về mối quan hệ thừa kế và vẫn ghi đè các hàm ảo.

Được thừa hưởng riêng từ lớp Base trong lớp Derived của bạn, hủy mọi mối quan hệ khái niệm giữa lớp gốc và lớp cơ sở. Lớp dẫn xuất chỉ được thực hiện dưới dạng lớp cơ sở, không có gì hơn. Thừa kế riêng tư chỉ là một kỹ thuật thực hiện và ngụ ý không có mối quan hệ giữa các lớp liên quan.

3

Phương thức f() của bạn vẫn bị ghi đè. Mối quan hệ này hữu ích khi triển khai mẫu thiết kế Template Method. Về cơ bản, bạn sẽ triển khai các bộ hoạt động chung trong lớp cơ sở. Các hoạt động của lớp cơ sở đó sau đó sẽ gọi một phương thức ảo, như là f() của bạn. Nếu lớp dẫn xuất ghi đè f(), các hoạt động của lớp cơ sở sẽ kết thúc gọi phiên bản có nguồn gốc là f(). Điều này cho phép các lớp dẫn xuất để giữ cho thuật toán cơ sở giống nhau nhưng thay đổi hành vi cho phù hợp với nhu cầu của chúng. Dưới đây là một ví dụ nhỏ:

#include <iostream> 

using namespace std; 

class Base 
{ 
public: 
    virtual void f() { cout<<"Base::f()" << endl; } 
protected: 
    void base_foo() { f(); } 
}; 

class DerivedOne: private Base 
{ 
public: 
    void f() { cout << "Derived::f()" << endl;} 
    void foo() { base_foo(); } 
}; 

class DerivedTwo: private Base 
{ 
public: 
    void foo() { base_foo(); } 
}; 

int main() 
{ 
    DerivedOne d1; 
    d1.foo(); 

    DerivedTwo d2; 
    d2.foo(); 
} 

Dưới đây là kết quả tại thời gian chạy:

$ ./a.out 
Derived::f() 
Base::f() 

lớp Cả hai có nguồn gốc gọi hoạt động cùng một lớp cơ sở nhưng hành vi này là khác nhau cho mỗi lớp dẫn xuất.

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