2011-01-28 31 views
8

tôi biên dịch mã này với GCC (4.2.1 của Apple xây dựng 5664)định nghĩa mơ hồ của nhà điều hành() với đa kế thừa

#include <cstddef> 

using std::size_t; 

template <char I> struct index { }; 

struct a 
{ 
    void operator()(size_t const &) { } 
}; 

struct b 
{ 
    template <char I> 
    void operator()(index<I> const &) { } 
}; 

struct c: public a, public b { }; 

int main (int argc, char const *argv[]) 
{ 
    c vc; 
    vc(1); 

    return 0; 
} 

và cung cấp cho tôi những lỗi sau:

main.cpp: In function ‘int main(int, const char**)’: 
main.cpp:22: error: request for member ‘operator()’ is ambiguous 
main.cpp:14: error: candidates are: template<char I> void b::operator()(const index<I>&) 
main.cpp:9: error:     void a::operator()(const size_t&) 

I don' t hiểu lý do tại sao mã này không rõ ràng; hai phương thức có chữ ký khác nhau.

+0

Tôi ngạc nhiên rằng Clang có thể biên dịch mã của bạn, trong khi GCC phàn nàn. – peoro

Trả lời

6

Sửa c theo cách này:

struct c: public a, public b 
{ 
    using a::operator(); 
    using b::operator(); 
}; 

C++ (trước C++ 0x) là loại vụng về trong kế thừa chức năng: nếu bạn cung cấp một hàm có cùng tên của một hàm lớp cơ sở nó ẩn lớp cơ sở.

Có vẻ như việc kế thừa từ hai lớp cũng có cùng một vấn đề.

// tìm kiếm tiêu chuẩn ...

+0

Đó chỉ là trường hợp nếu chúng có cùng chữ ký, những chức năng này không có. –

+0

@Zac Howland: không chắc chắn, bạn có thể đúng, nhưng GCC sẽ không biên dịch nó theo cách khác. Có thể một lỗi GCC? Clang sẽ biên dịch mà không có bất kỳ vấn đề mã OP ... – peoro

+5

@Zac Howland: ẩn xảy ra trên tên phù hợp không chữ ký. –

1

Không rõ ràng của nó vì bạn đang đi qua một hằng số nguyên có thể (có lẽ) được đúc thành một loại std::size_t hoặc index. Thay đổi main thành các mục sau và giải quyết vấn đề này:

int main (int argc, char const *argv[]) 
{ 
    c vc; 
    vc(static_cast<std::size_t>(1)); 

    return 0; 
} 

Với điều đó, rất có khả năng bạn không nên sử dụng đa thừa kế ở đây.

+1

Không thể truyền số nguyên thành loại chỉ mục. Và nếu bạn cố gắng biên dịch, nó không hoạt động. –

+0

@mattia: Bạn sẽ phải cụ thể hơn về vấn đề này. Với những gì bạn đã hiển thị, mã ở trên sẽ hoạt động (rõ ràng, bạn phải thay đổi dàn diễn viên nếu bạn muốn toán tử khác). @peoro: 'static_cast' thực hiện chính xác những gì anh ta đang làm ở đây - truyền một số nguyên thành một loại cụ thể. –

+0

@mattia: Hãy thử làm điều này thay vì nội tuyến 'static_cast' sau đó:' std :: size_t i = 1; vc (i); ' –

6

Độ phân giải tên được thực hiện trước khi quá tải.
Không có operator() trong c để trình biên dịch tìm kiếm operator() trong các lớp cơ sở của nó và tìm một số trong a và một khác trong tên b làm cho tên mơ hồ (và không xảy ra tình trạng quá tải).

Nếu bạn muốn loại bỏ tên mơ hồ bạn có thể gọi a::operator() một cách rõ ràng: vc.a::operator()(1);