2016-11-16 15 views
6
#include <iostream> 

struct A 
{ 
    virtual void foo(){ std::cout << "A"; }; 
}; 

struct B : public A 
{ 
private: 
    void foo() override { std::cout << "B"; } 
}; 

int main() 
{ 
    A *p = new B; 
    p->foo();  // prints B 

// B b; 
// b.foo();  // error: foo is private 
    return 0; 
} 

// g++ -std=c++11 -Wall -Wextra -Wpedantic main.cpp && ./a.out 

Vì vậy, chúng tôi có thể gọi B.foo() đa hình, nhưng không trực tiếp. Có trường hợp sử dụng nào không, khi ai đó muốn sử dụng chức năng này?Có trường hợp sử dụng cho các phương pháp riêng ảo công cộng không?

Trả lời

2

Nó ngăn bạn gọi phương thức không đa hình, đó là tất cả: sử dụng toán tử phân giải phạm vi để truy cập trực tiếp phương pháp có thể dẫn đến khó duy trì mã. Trong một môi trường mà bạn biết rằng không phải ai cũng là một người thực hiện có kinh nghiệm (các lập trình viên khoa học đóng góp cho một codebase lớn), bạn nên giới thiệu các mẫu để bảo vệ mã của bạn từ họ!

Điều đó nói rằng, Java rõ ràng cấm nó khi họ coi nó là kiểu xấu.

+1

Sau đó, một lần nữa, Java không cấm điều gì. –

5

Nó phụ thuộc vào thiết kế của lớp cơ sở. Giả sử bạn có một lớp cơ sở

class Stream { 
public: 
    virtual bool canSeek() = 0; 
    virtual void seek(int offset) = 0; 
}; 

Lưu ý: ví dụ này xuất phát từ NET thế giới, nơi mà các lớp cơ sở thư viện Stream lớp thực sự có một CanSeek tài sản ảo như vậy. Tôi không muốn thảo luận xem đây có phải là thiết kế tốt hay không, vì tôi có thể thấy các đối số hợp lệ cho cả hai bên. Nó đủ cho rằng các lớp cơ sở như vậy tồn tại trong thực tế.

Bây giờ, một lớp dẫn xuất có thể xác định rằng

class SpecificStream final : Stream { 
private: 
    virtual bool canSeek() { return false; } 
    virtual void seek(int offset) { throw "no seek for you"; } 
} 

Trong lớp có nguồn gốc này, thực tế là seek được thực hiện ở tất cả là bởi vì nó được yêu cầu về mặt kỹ thuật. Tuy nhiên, bất kỳ mã nào tương ứng với mã này SpecificStream đã biết rằng hàm seek hoàn toàn vô dụng với lớp này và không nên được gọi. Khi mã hóa với lớp cơ sở Stream, bạn có thể kiểm tra kết quả của canSeek() và gọi seek chỉ khi kết quả là đúng. Khi mã hóa với lớp SpecificStream, việc kiểm tra canSeek() là không hợp lý, vì kết quả của nó được biết đến tĩnh và chắc chắn không có ý nghĩa khi gọi seek(). Nếu các cuộc gọi như vậy sẽ là một lỗi lập trình viên, nó có ý nghĩa để giúp trình biên dịch cung cấp các thông điệp hữu ích cho các cuộc gọi như vậy.

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