2010-01-29 77 views
21

Trong C++, chức năng thành viên của lớp cơ sở có bị ghi đè bởi hàm lớp dẫn xuất của cùng tên, ngay cả khi nguyên mẫu (thông số, loại và constness) khác nhau? Tôi đoán đây là một câu hỏi ngớ ngẩn, vì nhiều trang web nói rằng nguyên mẫu hàm nên giống nhau cho điều đó xảy ra; nhưng tại sao mã dưới đây không biên dịch? Đó là một trường hợp thừa kế rất đơn giản, tôi tin.C++ thừa kế và chức năng ghi đè

#include <iostream> 
using std::cout; 
using std::endl; 

class A {}; 
class B {}; 

class X 
{ 
public: 
    void spray(A&) 
    { 
     cout << "Class A" << endl; 
    } 
}; 

class Y : public X 
{ 
public: 
    void spray(B&) 
    { 
     cout << "Class B" << endl; 
    } 
}; 

int main() 
{ 
    A a; 
    B b; 
    Y y; 

    y.spray(a); 
    y.spray(b); 

    return 0; 
} 

GCC ném

error: no matching function for call to `Y::spray(A&)' 
note: candidates are: void Y::spray(B&) 
+0

Có Câu hỏi thường gặp về C++ về cùng một vấn đề, để giải thích chi tiết nếu một số người yêu cầu nó :) http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq- 23.9 – legends2k

+1

Hơi nguy hiểm khi nói rằng chữ ký phải giống nhau. Chữ ký là cơ sở cho việc mang tên và liên kết. Hai thành viên của các lớp khác nhau luôn luôn có chữ ký khác nhau, ngay cả khi một người ghi đè khác. Tốt hơn là nên nói "cùng loại thông số, tên và độ chói", tôi nghĩ, ngay cả khi nó dài hơn. –

+0

@litb: Cảm ơn bạn đã làm rõ! Tôi đoán 'nguyên mẫu' là từ thích hợp ở đây, tôi đã thay đổi nó trong câu hỏi :) – legends2k

Trả lời

28

Các thuật ngữ dùng để mô tả này là "trốn", chứ không phải là "trọng". Một thành viên của lớp dẫn xuất sẽ, theo mặc định, làm cho bất kỳ thành viên nào của các lớp cơ sở có cùng tên không truy cập được, cho dù chúng có cùng chữ ký hay không. Nếu bạn muốn truy cập các thành viên lớp cơ sở, bạn có thể kéo chúng vào lớp dẫn xuất với khai báo using. Trong trường hợp này, hãy thêm thông tin sau vào class Y:

using X::spray; 
+0

Cảm ơn lời giải thích, điều đó đã làm rõ. Nó hoạt động khi tôi thêm chỉ thị sử dụng ở đây. Nhưng khi tôi thay đổi chữ ký phun để phun (int) trong X và phun (phao) trong Y và gọi y.spray (1); và y.spray (1.0f); nó hoạt động mà không có chỉ thị sử dụng. Làm thế nào mà? – legends2k

+2

Wow xin lỗi, xấu của tôi, nó vẫn chỉ nhìn thấy phun (phao) của Y, khi tôi làm y.spray (1); nó gõ phôi int vào phao ngầm. – legends2k

+2

Đây là một trong những câu trả lời xứng đáng với câu hỏi đặc biệt của riêng mình, được chế tác với rất nhiều bột tìm kiếm để mọi người có thể tìm thấy nó tốt hơn. – Wug

10

Đó là cái gọi là 'ẩn': Y::spray ẩn X::spray. Add sử dụng chỉ thị:

class Y : public X 
{ 
public: 
    using X::spray; 
    // ... 
}; 
5

Phạm vi và phạm vi lớp được lồng trong phụ huynh. Bạn có chính xác hành vi tương tự với các phạm vi lồng nhau khác (không gian tên, khối). Điều này xảy ra là khi tra cứu tên tìm kiếm định nghĩa của tên, nó sẽ tìm trong không gian tên hiện tại, sau đó trong không gian tên englobing và cứ như vậy cho đến khi tìm thấy một định nghĩa; tìm kiếm sau đó dừng lại (điều đó không tính đến các biến chứng được giới thiệu bởi tra cứu tên phụ thuộc đối số - một phần của các quy tắc cho phép sử dụng một hàm được định nghĩa trong không gian tên của một đối số của nó).

+0

Cảm ơn bạn đã giải thích lý do cơ bản đằng sau sự hinding; nó thực sự nói tại sao tôi nhận được lỗi đó ở nơi đầu tiên và tại sao chỉ thị sử dụng giải quyết nó. – legends2k

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