2010-09-02 36 views
16

Có thể làm cho các hàm thành viên của tôi final như trong Java, sao cho các lớp dẫn xuất không thể ghi đè chúng?Làm thế nào để xác định các hàm thành viên 'cuối cùng' cho một lớp

+0

Câu hỏi thú vị để hỏi trong cuộc phỏng vấn ... vì câu trả lời là không làm gì cả. (Tôi tin.) – Stephen

+0

Không có chức năng đặc biệt nào trong C++ tránh ghi đè, chỉ cần khai báo ảo và ghi đè. – ratty

+1

Câu hỏi không rõ ràng. Rằng bạn băn khoăn rằng nó đã ám chỉ đến tâm trí của tôi rằng bạn đang nói về các hàm ảo, trong trường hợp đó câu trả lời là không: một lớp bắt nguồn từ bất kỳ lớp nào có hàm ảo được chỉ định trong tổ tiên có thể ghi đè hàm. Như những người khác đã chỉ ra, sans "ảo", tất cả các chức năng không thể được ghi đè. Tôi không biết Java, vì vậy tôi không chắc chắn những gì nó cho phép khi .... –

Trả lời

9

Rất có thể thực tế là hành vi mặc định. I E. nếu bạn không khai báo các cá thể lớp của bạn một cách rõ ràng là virtual, chúng không thể là overridden trong các lớp con (chỉ hidden, một trường hợp khác - và hầu như luôn luôn sai).

C++ phiên bản thứ ba hiệu quả, mục 36 đề cập chi tiết đến điều này. Hãy xem xét

class B { 
public: 
    virtual void vf(); 
    void mf(); 
    virtual void mf(int); 
    ... 
}; 

class D: public B { 
public: 
    virtual void vf();    // overrides B::vf 
    void mf();      // hides B::mf; see Item33 
    ... 
}; 

D x;        // x is an object of type D 
B *pB = &x;      // get pointer to x 
D *pD = &x;      // get pointer to x 

pD->vf();       // calls D::mf, as expected 
pB->vf();       // calls D::mf, as expected 
pD->mf();       // calls D::mf, as expected 
pB->mf();       // calls B::mf - surprise! 
pD->mf(1);      // error - D::mf() hides B::mf(int)! 
pB->mf(1);      // calls B::mf(int) 

Vì vậy, đây không phải là cách chính xác final hoạt động trong Java, nhưng bạn chỉ có thể thực hiện việc này với C++. Một cách khác có thể là ngăn chặn phân lớp hoàn toàn. Giải pháp kỹ thuật, nhưng không tốt đẹp cho việc này là khai báo tất cả các nhà xây dựng của bạn private (và cung cấp một phương thức nhà máy tĩnh nếu bạn muốn cho phép tạo ra lớp của bạn, tất nhiên).

+0

nếu tôi không hiểu lầm, thì 'Ghi đè' là ẩn bản sao của lớp cơ sở, rất có thể trong trường hợp này. Điều tôi muốn là bắt buộc các lớp dẫn xuất luôn sử dụng/gọi hàm sao chép của lớp cơ sở. – Hemant

+0

@Hemant, xem các liên kết và ví dụ mã tôi đã thêm. –

+0

Tôi không biết Java, nhưng từ những gì tôi nghe tôi nghĩ trong Java bạn thậm chí không thể khai báo 'D :: mf()'. – sbi

3

Kiểm tra this từ Bjarne (Tôi có thể ngăn không cho người bắt nguồn từ lớp học của tôi?)

+0

Liên kết [trực tiếp] (http://www2.research.att.com/~bs/bs_faq2.html#no-derivation) có thể hữu ích hơn: p. – Stephen

+0

@Stephen: Tôi đặt nó vào. @chubsdad: Tôi hy vọng bạn không phiền. – sbi

+0

@sbi: Ồ, vâng, chỉnh sửa quyền. Tôi có những người đó. Tôi quên mất. > _ <. – Stephen

1

Trên thực tế nó là có thể nếu bạn đang sử dụng MSVC. Có một từ khóa sealed. Đây là một số example from msdn.

21

C++ 11 cho biết thêm một từ khóa theo ngữ cảnh final để hỗ trợ này:

class B 
{ 
    public: 
    virtual void foo() final; 
}; 
class D : B 
{ 
    public: 
    virtual void foo(); // error: declaration of 'foo' overrides a 'final' function 
}; 

final được hỗ trợ trong GCC 4.7 và Clang 3.0. Và như Sergius ghi chú trong câu trả lời của mình, MSVC++ hỗ trợ nó (với chính tả sealed), kể từ MSVC++ 2005. Vì vậy, nếu bạn đóng gói trong một vĩ mô nhỏ và thiết lập nó tùy thuộc vào trình biên dịch của bạn, bạn có thể được trên con đường của bạn với điều này. Chỉ cần đảm bảo rằng bạn thực sự là sử dụng trình biên dịch như vậy ít nhất mỗi lần như vậy, vì vậy bạn sẽ sớm phát hiện bất kỳ lỗi nào.

1

Chuẩn C++ 11 mới hiện hỗ trợ phần ghi đè rõ ràng và chức năng cuối cùng của thành viên!

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