2013-07-02 56 views
5

Vì vậy, dựa trên một tìm kiếm cursory, tôi đã biết rằng việc gọi một chức năng ảo (tinh khiết hoặc cách khác) từ một nhà xây dựng là một không đi. Tôi đã tái cơ cấu mã của mình để đảm bảo rằng tôi không làm điều đó. Trong khi điều này làm cho người dùng của các lớp học của tôi thêm một cuộc gọi chức năng bổ sung trong mã của họ, điều này thực sự không phải là lớn của một thỏa thuận. Cụ thể, thay vì gọi hàm tạo trong một vòng lặp, bây giờ chúng gọi hàm đó (trên thực tế!) Làm tăng hiệu suất của mã vì chúng ta không có việc xây dựng và phá hủy đối tượng được đề cập mỗi lần.Gọi chức năng ảo thuần túy từ chức năng thành viên lớp cơ sở trừu tượng?

Tuy nhiên, tôi đã tình cờ một cái gì đó thú vị ...

Trong lớp trừu tượng tôi có một cái gì đó như thế này:

// in AbstractClass.h: 
class AbstractClass { 
public: 
    AbstractClass() {} 
    virtual int Func(); //user can override 
protected: 
    // Func broken up, derived class must define these 
    virtual int Step1() = 0; 
    virtual int Step2() = 0; 
    virtual int Step3() = 0; 
// in AbstractClass.cpp: 
int AbstractClass::Func() { 
    Step1(); 
    // Error checking goes here 
    Step2(); 
    // More error checking... 
    // etc... 
} 

Về cơ bản, có một cấu trúc phổ biến mà các chức năng ảo tinh khiết theo nhất của thời gian, nhưng nếu họ không Func() là ảo và cho phép các lớp dẫn xuất để xác định thứ tự. Tuy nhiên, mỗi bước phải được thực hiện trong các lớp dẫn xuất.

Tôi chỉ muốn chắc chắn rằng không có gì mà tôi nhất thiết phải làm sai ở đây vì hàm Func() gọi các hàm ảo thuần túy. Đó là, sử dụng lớp cơ sở, nếu bạn gọi StepX(), những điều xấu sẽ xảy ra. Tuy nhiên, lớp được sử dụng bằng cách tạo một đối tượng có nguồn gốc và sau đó gọi hàm Func() (ví dụ: MyDerivedObject.Func();) trên đối tượng dẫn xuất đó, nên có tất cả các hàm ảo thuần túy bị quá tải đúng cách.

Có bất kỳ điều gì tôi thiếu hoặc làm không chính xác bằng cách làm theo phương pháp này không? Cảm ơn đã giúp đỡ!

+1

Đây là ví dụ về sách giáo khoa về sử dụng [Thành ngữ giao diện không phải ảo] (http://en.wikipedia.org/wiki/Non-virtual_interface_pattern) để triển khai [Mẫu phương thức mẫu] (http: // vi. wikipedia.org/wiki/Template_pattern). – Casey

+0

Chỉ cần làm rõ, có sự khác biệt lớn giữa "gọi các hàm ảo trong một hàm tạo" và "gọi các hàm thuần ảo". Trước đây là khó khăn và nản chí (mặc dù hợp lệ), sau này là phẳng ra sai (và cũng không hoàn toàn tầm thường để làm). –

+0

Gọi một hàm ảo trong một hàm tạo hoặc hàm hủy không phải là "không đi", trừ khi bạn không bận tâm để hiểu cách chúng hoạt động. –

Trả lời

4

Func đang gọi điện thoại ảo, không phải là ảo ảo. Bạn sẽ phải hội đủ điều kiện các cuộc gọi với toán tử phạm vi, tức là AbstractClass :: Step1() để gọi hàm THAT (virtual pure). Vì bạn không, bạn sẽ luôn nhận được một lớp thực thi.

+0

Vì vậy, không có vấn đề gì tôi làm, trừ khi tôi làm một cái gì đó thực sự hacky như AbstractClass :: Step3(), các chức năng sẽ được ghi đè bởi lớp dẫn xuất? Có lá cờ đỏ nào với cách tiếp cận này liên quan đến thực hành mã C++ tốt không? –

+3

Trên thực tế, đó là những gì làm cho OO và C++ mạnh mẽ. Bạn có thể viết "thủ tục" trong đó lớp dẫn xuất được xác định chi tiết. Hãy suy nghĩ về một giao thức comm. EstablishConnection(); trong khi(!Xong()) {SendRequest(); GetResponse();} TerminateConnection(); Tất cả các phương thức này có thể là "ảo", một lớp dẫn xuất sử dụng TCP, một lớp khác sử dụng cơ chế "kết nối" cao hơn, hoặc một điểm đơn giản hơn để giao thức RS-232 không có gì trong các phương thức của chúng (Setup/TerminateSession(). Tuy nhiên, bạn đã xác định một khuôn khổ nhỏ có thể được triển khai và mở rộng dễ dàng. – franji1

+0

Cảm ơn lời giải thích. Tôi khá mới đối với một số khái niệm OO này và tôi muốn càng sắc nét càng tốt ... –

1

Một hàm ảo trong lớp cơ sở làm cho các lớp dẫn xuất có thể ghi đè lên nó. Nhưng dường như mọi thứ dừng lại ở đó.

Nhưng nếu hàm lớp ảo cơ sở là thuần túy, sẽ buộc các lớp dẫn xuất thực hiện hàm.

-1

Là một nhận xét phụ, bạn có thể đặt các phương thức Step1, Step2, Step3 riêng tư để bạn có thể ngăn trình biên dịch trực tiếp gọi chúng.

+1

Bạn có nên nhận xét không? – lpapp

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