2012-03-19 33 views
16

Tôi có thể hiểu rằng có thể có lý do để tuyên bố một chức năng ảo được thực thi (trái ngược với thuần túy) riêng tư hoặc được bảo vệ. Ví dụ, nếu bạn khai báo một phương thức ảo được thực hiện như được bảo vệ, lớp con của bạn có thể gọi phương thức của lớp cơ sở (và không ai khác có thể). Nếu bạn khai báo nó riêng tư, hơn là chỉ có lớp cơ sở có thể gọi thực hiện mặc định của phương thức ảo.Có sự khác biệt nào giữa chức năng ảo thuần túy được bảo vệ và riêng tư không?

Tuy nhiên, với ảo thuần túy, không có triển khai cơ sở ... Vì vậy, nó không phải là chức năng tương đương với tuyên bố một ảo thuần túy là riêng tư hoặc được bảo vệ? Một ảo tinh khiết được bảo vệ không có ý nghĩa bởi vì bạn không bao giờ có thể gọi phương thức tương ứng của lớp cơ sở. Có bất kỳ tình huống nào mà một ảo thuần túy được bảo vệ có ý nghĩa gì không?

Có một vài chủ đề tương tự về SO, nhưng tôi không thể tìm thấy bất kỳ điều gì trả lời ngắn gọn câu hỏi của tôi.

+0

Bạn có thể triển khai 'friend' cho giao diện. – Matthew

+6

Phương pháp ảo thuần túy có thể có phần thân và nó có thể được gọi rõ ràng như base :: foo(). – iammilind

Trả lời

8

Có bất kỳ tình huống nào trong đó một ảo thuần túy được bảo vệ làm cho bất kỳ cảm giác nào không?

Tôi nghĩ rằng bạn có ý nói riêng tư ở đây (thay vì được bảo vệ), nhưng tôi nghĩ rằng tôi hiểu ý của bạn. Trong thực tế, kiểu truy cập của một virtual thuần túy có thể được ghi đè trong các lớp dẫn xuất. Dưới đây là ví dụ có thể giúp bạn thấy sự khác biệt giữa một máy ảo thuần túy riêng tư và được bảo vệ:

class Parent 
{ 
    protected: virtual void foo() = 0; 
    private: virtual void bar() = 0; 
    public:   void test() { foo(); bar(); } 
}; 

class Child : public Parent 
{ 
    public: void test2() { foo(); /* bar(); // cannot be called here */ } 
}; 

class GrandChild : public Child 
{ 
    // access types here can be anything for this example 
    public: void foo() { cout << "foo" << endl; } 
    public: void bar() { cout << "bar" << endl; } 
}; 
+0

Cảm ơn ví dụ. Chỉ cần làm rõ - một virtual virtual private có thể không bao giờ được gọi bởi bất kỳ hậu duệ nào của nó (nhưng có thể được thực thi bởi chúng, vì vậy lớp cơ sở có thể gọi phương thức của hậu duệ của nó?) – Prismatic

+0

Không. Trong ví dụ này, nếu GrandChild gọi 'foo () 'bên trong một phương thức khác của nó, nó sẽ biên dịch và làm việc như mong đợi,' GrandChild :: foo' sẽ được gọi. – mfontanini

+2

Có Pris, một chức năng ảo có thể được ghi đè bằng một kiểu truy cập khác có thể mở ra khả năng truy cập của nó. – LiquidAsh

4

Chức năng ảo thuần túy đầu tiên có thể được triển khai!

#include <iostream> 

class Animal 
{ 
public: 
    void eat(void); 
protected: 
    virtual void doEat(void)=0; 
}; 
void Animal::eat(void) 
{ 
    doEat(); 
} 
void Animal::doEat(void) 
{ 
    std::cout << "animal" << std::endl; 
} 

class Tiger : public Animal 
{ 
private: 
    virtual void doEat(void) 
    { 
    Animal::doEat();//here is the difference between protected and private 
    std::cout << "tiger" << std::endl; 
    } 
}; 

int main(void) 
{ 
    Animal *p = new Tiger(); 
    p->eat(); 
    return 0; 
} 

Thứ hai, Herb Sutter giải thích khi sử dụng "ảo cá nhân" hoặc "ảo được bảo vệ", bạn có thể đọc từ article này .Tôi nghĩ rằng điều này giải thích lý do tại sao chúng tôi làm được điều này không chỉ chúng ta có thể bài báo cho biết:" Ưu tiên tạo các hàm ảo riêng, Chỉ khi các lớp dẫn xuất cần gọi thực hiện cơ sở của một hàm ảo, làm cho hàm ảo được bảo vệ ", câu hỏi của bạn là về hàm ảo thuần túy, tôi không hoàn toàn chắc chắn liệu có đáp ứng nguyên tắc này hay không.

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