2009-05-20 36 views
40

thể trùng lặp:
C++ overload resolutionTrọng Chức năng quá tải của cơ sở trong C++

Tôi chạy vào một vấn đề mà sau giờ học của tôi gạt một chức năng của lớp cơ sở của nó, tất cả các phiên bản quá tải các chức năng sau đó được ẩn đi. Đây có phải là do thiết kế hay tôi chỉ làm điều gì sai?

Ví dụ:

class foo 
{ 
    public: 
    foo(void); 
    ~foo(void); 
    virtual void a(int); 
    virtual void a(double); 
}; 

class bar : public foo 
{ 
    public: 
    bar(void); 
    ~bar(void); 
    void a(int); 
}; 

sau đây sẽ đưa ra lỗi biên dịch cho biết không có hàm (kép) trong thanh.

main() 
{ 
    double i = 0.0; 
    bar b; 
    b.a(i); 
} 
+0

Sẽ hữu ích nếu bạn đăng (nếu có thể) mã thực tế. Mã bạn đăng thiếu một số chi tiết, như dấu chấm phẩy sau định nghĩa lớp và kiểu trả về cho 'a' trong' bar' ... –

+1

Tôi không thể đăng mã thực. Tôi đã thêm chi tiết vào bài đăng, điều này không thực sự có ý nghĩa như một bài tập về cú pháp. – Greg

+5

http://stackoverflow.com/questions/72010/c-overload-resolution –

Trả lời

62

Trong thanh lớp, thêm

using foo::a; 

Đây là một chung 'Gotcha' trong C++. Khi một kết hợp tên được tìm thấy trong phạm vi lớp, nó không nhìn xa hơn cây thừa kế cho quá tải. Bằng cách chỉ định khai báo 'sử dụng', bạn mang tất cả các tình trạng quá tải của 'a' từ 'foo' vào phạm vi 'thanh'. Sau đó, quá tải hoạt động đúng cách.

Hãy nhớ rằng nếu có mã hiện tại bằng cách sử dụng lớp 'foo', ý nghĩa của nó có thể bị thay đổi do quá tải bổ sung. Hoặc quá tải bổ sung có thể giới thiệu sự mơ hồ và mã sẽ không biên dịch được.Điều này được chỉ ra trong câu trả lời của James Hopkin.

+0

Lời giải thích hoàn hảo, cảm ơn bạn rất nhiều! – Greg

+3

Điều đáng lưu ý là điểm của James Hopkin về ý nghĩa thay đổi mã hợp lệ khi các hàm bổ sung được thêm vào một lớp cơ sở. –

+0

@Thomas: Đã chỉnh sửa để thêm điểm đó. Cảm ơn. –

18

Đó là cách ngôn ngữ được sử dụng để hoạt động. Trước khi sử dụng từ khóa, nếu bạn gạt một chức năng quá tải, bạn phải quá tải chúng tất cả:

class bar : public foo 
{ 
    public: 
    bar(void); 
    ~bar(void); 
    a(int); 
    a(double d) { foo::a(d); } // add this 
} 

này khó chịu người đủ rằng ủy ban ngôn ngữ thêm sử dụng tính năng, nhưng một số thói quen cũ chết cứng ; và những người quen & dao găm; có một lý lẽ tốt.

Như James Hopkins chỉ ra, bằng cách thêm sử dụng, lập trình viên thể hiện ý định rằng lớp dẫn xuất sẽ không thêm bất kỳ phần ghi đè nào trong tương lai của foo :: a() vào danh sách các chữ ký chấp nhận được.

Dưới đây là một ví dụ về những gì ông mô tả: "Xuất phát :: đúp"

#include <iostream> 
class Base { 
public: 
    virtual void f(double){ std::cout << "Base::Double!" << std::endl; } 
    // virtual void f(int) { std::cout << "Base::Int!" << std::endl; } // (1) 
    virtual ~Base() {} 
}; 

class Derived : public Base { 
public: 
    // using Base::f; // (2) 
    void f(double) { std::cout << "Derived::Double!" << std::endl; } 
}; 

int main(int, char **) { 
    Derived d; 
    d.f(21); 
    return 0; 
} 

Kết quả sẽ được bởi vì trình biên dịch sẽ thúc đẩy đối số nguyên cho một đôi. g ++ 4.0.1 -Wall sẽ không cảnh báo rằng chương trình khuyến mãi này đã xảy ra.

Bỏ ghi chú (1) để mô phỏng thay đổi trong tương lai thành Cơ sở thêm phương thức Base :: f (int). Mã biên dịch, một lần nữa mà không cần cảnh báo ngay cả với -Wall và "Derived :: Double!" vẫn là đầu ra.

Bây giờ bỏ ghi chú (2) để mô phỏng quyết định của lập trình có nguồn gốc để bao gồm tất cả chữ ký cơ sở :: f. Mã biên dịch (không có cảnh báo), nhưng đầu ra bây giờ là "Base :: Int!".

& dagger; Tôi không thể nghĩ ra một từ tiếng Anh cho "những người có thói quen" và "nghiện" là quá mạnh.

+0

Điều này không đúng chút nào, bạn có thể ghi đè lên chỉ một chức năng. –

+0

Phòng thủ duy nhất của tôi là tôi đã viết rất nhiều C++ trước năm 1996. Sigh. –

+0

Ah, thời gian cũ tốt :) –

11

Đó là theo thiết kế. Độ phân giải quá tải bị giới hạn ở một phạm vi duy nhất. Nó ngăn cản một số trường hợp khó chịu của việc thay đổi mã hợp lệ khi các hàm bổ sung được thêm vào một lớp cơ sở hoặc phạm vi không gian tên.

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