2013-04-05 12 views
17

Trong lớp học của tôi được gọi là Mat, tôi muốn có một hàm có chức năng khác làm tham số. Ngay bây giờ tôi có 4 chức năng dưới đây, nhưng tôi gặp lỗi khi gọi print(). Dòng thứ hai mang lại cho tôi một lỗi, nhưng tôi không hiểu tại sao, vì cái đầu tiên hoạt động. Sự khác biệt duy nhất là hàm f không phải là thành viên của lớp Mat, nhưng f2 là. Thất bại là: error: no matching function for call to Mat::test(< unresolved overloaded function type>, int)'C++ - <loại chức năng quá tải chưa được giải quyết>

template <typename F> 
int Mat::test(F f, int v){ 
    return f(v); 
} 

int Mat::f2(int x){ 
    return x*x; 
} 

int f(int x){ 
    return x*x; 
} 

void Mat::print(){ 
    printf("%d\n",test(f ,5)); // works 
    printf("%d\n",test(f2 ,5)); // does not work 
} 

Tại sao điều này xảy ra?

+1

Có phải 'f2' tĩnh hay không? –

+0

Thử thay đổi lệnh printf thành printf ("% d \ n", kiểm tra (Mat :: f2, 5)); – 2to1mux

+0

Bạn có nhiều hơn một quá tải 'f2'? –

Trả lời

3

Vấn đề ở đây là f2 là phương pháp trên Mat, trong khi f chỉ là một chức năng miễn phí. Bạn không thể tự gọi số f2, nó cần một phiên bản Mat để gọi nó. Cách đơn giản nhất xung quanh này có thể là:

printf("%d\n", test([=](int v){return this->f2(v);}, 5)); 

các = sẽ chụp this, đó là những gì bạn cần phải gọi f2.

+0

Vì f2 và in là cả hai chức năng thành viên của Mat, không in được phép gọi f2 mà không tham chiếu đến đối tượng Mat? – 2to1mux

+0

Wow, công trình này (với một vài tinh chỉnh từ mã gốc). +1 từ tôi –

+0

-1. thông báo lỗi nói rằng lỗi xảy ra do một hàm bị quá tải, và không phải vì cú pháp cuộc gọi hàm của mẫu chức năng là sai (đó là những gì bạn nói). –

31

Loại pointer-to-member-function khác với pointer-to-function.

Kiểu của một hàm là khác nhau tùy thuộc vào việc nó là một chức năng bình thường hoặc một hàm thành viên không tĩnh của một số lớp:

int f(int x); 
the type is "int (*)(int)" // since it is an ordinary function 

int Mat::f2(int x); 
the type is "int (Mat::*)(int)" // since it is a non-static member function of class Mat 

Lưu ý: nếu đó là một hàm thành viên tĩnh của lớp Fred, kiểu của nó giống như một hàm bình thường: "int (*)(char,float)"

In C++, member functions have an implicit parameter which points to the object (the this pointer inside the member function). Normal C functions can be thought of as having a different calling convention from member functions, so the types of their pointers (pointer-to-member-function vs pointer-to-function) are different and incompatible. C++ introduces a new type of pointer, called a pointer-to-member, which can be invoked only by providing an object.

NOTE: do not attempt to "cast" a pointer-to-member-function into a pointer-to-function; the result is undefined and probably disastrous. E.g., a pointer-to-member-function is not required to contain the machine address of the appropriate function. As was said in the last example, if you have a pointer to a regular C function, use either a top-level (non-member) function, or a static (class) member function.

Thông tin thêm về điều này Herehere.

+0

Nhưng điều này không giải thích tại sao mẫu không thể giải quyết nó. Hay tôi đang thiếu một cái gì đó? –

+0

@LuchianGrigore Đây là cách tôi hiểu nó. Trình biên dịch mong đợi một kiểu cung cấp một 'toán tử gọi' hoặc thấy nếu nó có thể tìm thấy một hàm phù hợp với' int f (int) 'có thể truy cập từ Mat :: Test. Và theo mô tả ở trên, hàm con trỏ tới hàm thành viên so với hàm con trỏ tới hàm là khác nhau và không tương thích'. Vì vậy, nó sẽ không khớp với 'this-> f2' như một hàm. Đây chỉ là sự hiểu biết của tôi. Tôi thậm chí không biết về điều này trước ngày hôm nay :) –

+0

Liên kết dường như đã chết. – derM