2015-07-01 27 views
8

xem xét mã:Gọi phương pháp trẻ từ phương pháp cơ bản mà không cần tham khảo ảo hoặc

#include <iostream> 

class A { 
public: 
    void g() {std::cout << "Call from A" << std::endl;} 
    void f() {g();} 
}; 

class B : public A { 
public: 
    void g() {std::cout << "Call from B" << std::endl;} 
}; 

int main() { 
    B b; 
    b.f(); // "Call from A" 
} 

Nếu tôi làm A::g() ảo, nó sẽ tạo ra "Gọi từ B".

tôi luôn luôn hiểu "ảo" hữu ích khi chúng ta muốn một giao diện để cho phép đa hình, nói A *a = new B(); a->f(), nhưng ví dụ này chỉ ra rằng virtual cũng được yêu cầu trong tình huống này. Sự hiểu biết của tôi về ví dụ này là cuộc gọi g() trên A::f chính thức tương đương với this->g() và đây là con trỏ.

Tuy nhiên, đây không phải là những gì tôi thực sự muốn: trong ví dụ thật của tôi, tôi có một mẫu chung lớp A với một phương pháp chung A::simulate (nói A::f), có sử dụng phương pháp khác nhau (nói A::g()), một số trong đó được ghi đè theo phân lớp (giả sử B). Những gì tôi muốn là có phương thức A::simulate theo cách mà mã sẽ được biên dịch trong các lớp con của A như thể nó đã được định nghĩa trên các lớp con sao cho tôi không có cùng một mã logic được mã hóa nhiều lần. Tôi có thể làm cái này như thế nào?

Điều này là do giao diện của tôi sẽ không yêu cầu đa hình bởi vì người dùng sẽ luôn cần phải biên dịch mã (tức là chỉ là tiêu đề).

+7

Hãy lớp cơ sở của bạn một CRTP lớp mẫu. –

+0

Bạn có thể giải thích bằng các từ khác nhau vấn đề nếu bạn tạo A :: g() ảo không? –

+0

@ Khnle-Kevin: tại sao tôi nên tạo A :: g() ảo? Đối với tôi, đa hình hay không là một phần của giao diện tôi đang sản xuất. Vì tôi không thấy tính đa hình giúp * trong trường hợp sử dụng cụ thể của tôi như thế nào *, tôi không có lý do thuyết phục để thêm nó. Tôi muốn biết nếu tôi * thực sự * cần thiết để thêm nó vì ngôn ngữ tôi đang sử dụng. –

Trả lời

11

Bạn chỉ có thể làm cho lớp cơ sở của bạn một CRTP (như bạn đã đề cập đến nó đã là một lớp templated anyway):

#include <iostream> 

template<class Derived> 
class A { 
public: 
    void g() {std::cout << "Call from A" << std::endl;} 
    void f() { static_cast<Derived*>(this)->g();} 
      // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Call g() from Derived 
}; 

class B : public A<B> { 
public: 
    void g() {std::cout << "Call from B" << std::endl;} 
}; 

int main() { 
    B b; 
    b.f(); // "Call from B" 
} 
+2

Mẫu đẹp. Cảm ơn bạn rất nhiều! –

+0

@ J.C.Leitão Có, nó rất hữu ích cho một số trường hợp sử dụng (giao diện mixin, chính sách dựa trên desgns, vv). Đặc biệt hữu ích cho các thiết kế nhúng, nơi bạn muốn tránh các chi phí bổ sung được giới thiệu với vtables, và cũng biết bạn sẽ không cần cấu hình thời gian chạy (nhưng chỉ cấu hình các thành phần phần cứng thực sự có sẵn của bạn tại thời gian biên dịch). –

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