2013-04-05 29 views
17

W mojej klasie o nazwie Mat, chcę mieć funkcję, która przyjmuje inną funkcję jako parametr. Teraz mam 4 funkcje poniżej, ale dostaję błąd podczas wywoływania print(). Druga linia daje mi błąd, ale nie rozumiem dlaczego, ponieważ pierwszy działa. Jedyna różnica polega na tym, że funkcja f nie należy do klasy Mat, ale jest f2. Niepowodzenie jest: error: no matching function for call to Mat::test(< unresolved overloaded function type>, int)'C++ - <nierozstrzygnięty typ funkcji przeciążonej>

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 
} 

Dlaczego tak się dzieje?

+1

Czy 'f2' jest statyczne czy nie? –

+0

Spróbuj zmienić wywołanie printf na printf ("% d \ n", test (Mat :: f2, 5)); – 2to1mux

+0

Czy masz więcej niż jedno przeciążenie 'f2'? –

Odpowiedz

3

Problem polega na tym, że f2 to metoda na Mat, a f to tylko bezpłatna funkcja. Nie możesz samodzielnie wywołać f2, aby wywołać tę funkcję, musisz wykonać instancję Mat. Najprostszym sposobem obejścia tego może być:

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

= będzie przechwytywać this, co jest, co trzeba zadzwonić f2.

+0

Ponieważ f2 i print są funkcjami składowymi maty, czy nie można drukować do wywoływania f2 bez odwoływania się do obiektu Mat? – 2to1mux

+0

Wow, to działa (z kilkoma poprawkami z oryginalnego kodu). +1 ode mnie –

+0

-1. komunikat o błędzie mówi, że błąd występuje z powodu przeciążenia funkcji, a nie dlatego, że składnia funkcji wywołania funkcji jest nieprawidłowa (tak się mówi). –

31

Typ pointer-to-member-function różni się od .

Rodzaj funkcji różni się w zależności od tego, czy jest to zwykła funkcja lub funkcją niestatyczny członkiem jakiejś klasy:

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

I

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

Uwaga: jeśli jest to statyczna funkcja członkowska klasy Fred, jej typ jest taki sam, jak gdyby był zwykłą funkcją: "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.

Więcej informacji na ten temat: Here i here.

+0

Ale to nie wyjaśnia, dlaczego szablon nie można go rozwiązać. Czy może czegoś brakuje? –

+0

@LuchianGrigore Tak to zrozumiałem. Kompilator oczekuje typu, który udostępnia 'operator połączeń' lub widzi, czy może znaleźć funkcję, która pasuje do' int f (int) 'osiągalnej z Mat :: Test. I zgodnie z powyższym opisem funkcja "wskaźnik do członka" a wskaźnik do funkcji są różne i niekompatybilne ". Więc nie będzie pasował do tego 'this-> f2' jako funkcji. To tylko moje zrozumienie. Jeszcze o tym nie wiedziałem :) –

+0

Linki wydają się być martwe. – derM