2014-08-28 14 views
11
#include <iostream> 

template<typename Impl> 
struct renderer{ 
    void get(){ 
     static_cast<Impl*>(this)->get(); 
    } 
}; 
struct open_gl : public renderer<open_gl>{ 
    void get(){ 
     std::cout << "OpenGL" << std::endl; 
    } 
}; 
struct direct_draw : public renderer<direct_draw>{ 
    void get(){ 
     std::cout << "DX" << std::endl; 
    } 
}; 
template<typename T> 
void print_renderer(renderer<T> r){ 
    r.get(); 
} 
int main() { 
    auto gl = open_gl(); 
    auto dx = direct_draw(); 
    print_renderer(gl); 
    print_renderer(dx); 
} 
  1. Tại sao tôi không thể thay đổi các tham số của print_renderer để void print_renderer(const renderer<T> &r)? cannot convert 'this' pointer from 'const renderer<open_gl>' to 'renderer<open_gl> &' 'đa hình tĩnh trong C++

  2. Tại sao tôi lại nhận được một lỗi runtime khi tôi đổi tên các phương pháp get trong open_gl từ có được để get1? Điều này có nên kích hoạt lỗi trình biên dịch không? Error = Stack overflow

** Lưu ý Tôi đang sử dụng mới nhất MSVC

+1

Và ... trộn-n-match! http://coliru.stacked-crooked.com/a/25722fa147efbbd3 –

Trả lời

12

1)get không phải là một chức năng const thành viên: nó không thể thực hiện lời hứa của không sửa đổi const) tranh luận (của bạn.

Bạn có thể tuyên bố get như const, và nó biên dịch tốt:

void get() const { ... } 

2) Phương pháp cơ sở get sẽ được gọi là, đi sâu vào đệ quy vô hạn: Stack Overflow.

Nếu bạn khai báo chức năng của bạn override (nó cần phải được ảo), trình biên dịch sẽ ném ra một lỗi nếu nó không thực sự ghi đè lên một phương pháp cơ bản:

void get1() override { ... } // Compiler error 
void get() override { ... } // Ok 

Lưu ý:

Tiêu đề là "Đa hình tĩnh trong C + +", nhưng tôi nghĩ rằng bạn hiểu sai đa hình tĩnh là gì: nó không (phải) sử dụng thừa kế (như bạn đã làm). Thay vào đó, việc nhập kiểu mẫu vịt thời gian biên dịch sẽ tĩnh "giải quyết" các cuộc gọi hàm cho bạn.

Đó là, bạn không cần phải loại liên quan, bạn không cần các lớp cơ sở renderer ở tất cả, và bạn chỉ có thể làm như sau (trong trường hợp này, đổi tên để get1sẽ gây ra một lỗi biên dịch) :

#include <iostream> 

struct open_gl { 
    void get(){ 
     std::cout << "OpenGL" << std::endl; 
    } 
}; 
struct direct_draw { 
    void get(){ 
     std::cout << "DX" << std::endl; 
    } 
}; 

template<typename T> 
void print_renderer(T r){ 
    r.get(); 
} 

int main() { 
    auto gl = open_gl(); 
    auto dx = direct_draw(); 
    print_renderer(gl); 
    print_renderer(dx); 
} 

Live demo

+0

Cảm ơn, về câu hỏi thứ hai của tôi. Có thể ném lỗi trình biên dịch khi 'get' không được triển khai không? Một cái gì đó như ghi đè? –

+0

@MaikKlein có xem chỉnh sửa của tôi – quantdev

+0

Làm cách nào để tạo ra 'void get()' ảo nếu tôi muốn đa hình tĩnh? –

5
  1. becuase get không được đánh dấu const.
  2. Bởi vì phương pháp lớp cơ sở được sử dụng (không liên quan đến diễn viên), và nó đi vào vòng lặp vô hạn.