2013-04-05 56 views
5

Tôi thường sử dụng các hàm ảo thuần túy cho các phương thức được mã của tôi yêu cầu để hoạt động tốt. Vì vậy, tôi tạo ra các giao diện và sau đó những người dùng khác thực hiện các lớp dẫn xuất của họ. Các lớp dẫn xuất chỉ có các hàm ảo này là công khai trong khi một số phương thức bổ sung nên được thực hiện dưới dạng riêng tư vì mã của tôi không gọi chúng. Tôi không biết nếu điều này có thể được coi là một thực hành tốt của OOP (có bất kỳ mẫu thiết kế nào không?). Dù sao, câu hỏi của tôi là: Người dùng có thể quá tải một chức năng ảo thuần túy không?Quá tải chức năng ảo tinh khiết

ví dụ:

class Base 
{ 
public: 
Base(); 
virtual ~Base(); 
virtual void foo(int,double)=0; 
}; 

class Derived: 
public Base 
{ 
private: 
    // methods 
public: 
Derived(); 
virtual ~Derived(); 
virtual void foo(int, double, double); //this doesn't work 
}; 

Một giải pháp có thể là:

virtual void foo(int,double,double=0)=0; 

trong lớp cơ sở nhưng nó là rất hạn chế. Bạn nghĩ về điều gì?

+1

Quá tải chức năng đại diện cho ** API khác **. Lớp cơ sở trừu tượng đại diện cho ** API nhất quán **. Vì vậy, không, điều này không có ý nghĩa. –

+0

Chẳng phải ví dụ của bạn còn thiếu 'class Derived: Base'? – nonsensickle

+0

@nonsensical: đúng, tôi vừa chỉnh sửa. cảm ơn – Ale

Trả lời

9

Hai chức năng này khác nhau. Phần sau không ghi đè số điện thoại

virtual void foo(int,double)=0; 
virtual void foo(int, double, double); 

thứ hai là hàm ảo mới cụ thể có nguồn gốc.

Nếu bạn đặt override vào cuối quá trình biên dịch sẽ khiếu nại rằng bạn không ghi đè bất cứ điều gì. Đây là C++ 11 kiểm tra mặc dù.

virtual void foo(int, double, double) override; 

Người dùng có thể ghi đè chức năng ảo tinh khiết để xác nhận sử dụng override ở cuối hàm để xác minh. Trong trường hợp của bạn, chức năng thứ hai chỉ có thể được truy cập bằng cách sử dụng con trỏ có nguồn gốc hoặc loại. (mặc dù nó không thể được khởi tạo trừ khi hàm ảo thuần túy được ghi đè và thực hiện đúng cách, cho đến khi nó là một lớp trừu tượng). Do đó nếu nó không được dự định để được overidden thêm bởi các lớp học có nguồn gốc từ Derived sau đó làm cho nó ảo là một chi phí như anyway nó không phải là overidding phương pháp cơ bản.

+0

Tôi chỉ viết về 'ghi đè' khi câu trả lời này xuất hiện. Vì vậy, ở đây ít nhất là liên kết: http://msdn.microsoft.com/en-us/library/vstudio/jj678987.aspx – Kupto

+0

@Kupto: tại sao trong ví dụ, trước hết là funcC (double = 0.0) ghi đè hoạt động trong khi ở mã thứ hai nó không hoạt động? – Ale

+0

@Một lần tôi vừa thử nó và có vẻ như từ khóa 'override' trong ví dụ đầu tiên là dư thừa, nếu xem xét ý kiến. – Kupto

4

Bạn không thể.

Giả sử bạn có con trỏ Base, trỏ đến đối tượng Derived. Có con trỏ Base, bạn có "quyền truy cập" chỉ với giao diện của Base (trừ khi bạn truyền tới con trỏ Derived, nhưng đây không phải là những gì bạn cần).

+0

vâng, đây là một vấn đề. Vì vậy, giải pháp duy nhất là tạo ra một lớp trừu tượng nhưng không phải là một giao diện. Phải không? – Ale

+0

@Ale - Tôi không hiểu điểm của bạn. Sự khác nhau giữa 'interface' và' abstract class' trong C++ là gì? –

+0

[link] (http://stackoverflow.com/questions/15387581/more-methods-in-derived-classes-than-base-class), một lớp dẫn xuất có thể có nhiều hàm hơn lớp trừu tượng. Thay vào đó, một giao diện giới hạn số phương thức (theo ý kiến ​​của tôi). – Ale

3

Chức năng quá tải chỉ là một chức năng có cùng tên với tên khác, nhưng chấp nhận một tập hợp các thông số khác, tức là chức năng khác nhau. Nó không liên quan gì đến việc một hoặc nhiều chức năng quá tải là ảo hay không.

Trong ví dụ bạn đã trình bày, tôi tin rằng người dùng có thể quá tải chức năng thuần ảo, nhưng chỉ sau khi ghi đè lên. Và bạn không thể truy cập trực tiếp hàm từ lớp cơ sở - bạn cần phải đưa con trỏ lớp cơ sở đến con trỏ lớp dẫn xuất.

0

Như được chỉ ra bởi những người khác, nó sẽ không hoạt động.

kín đáo hơn, đây là những gì xảy ra

Derived d; 
d.foo(5, 10.0); // Works as expected 

Base &b = d; // b is polymorphic 
b.foo(3,10,4); // foo(int, double, double) is not in class Base, hence compile-time resolution fails! 
0

Nó không phải là trọng như chữ ký chức năng khác nhau.Theo quy tắc đa hình để ghi đè lên một hàm, các chữ ký và loại hàm sẽ giống nhau.

Trong trường hợp này, các chức năng này khác nhau. void ảo foo (int, double) = 0; void ảo foo (int, double, double);

0

Không quá tải foo trong lớp cơ sở là giải pháp đơn giản nhất?

class Base 
{ 
public: 
Base(); 
virtual ~Base(); 
virtual void foo(int,double)=0; 
virtual void foo(int,double,double)=0; 
}; 
Các vấn đề liên quan