2012-04-04 8 views
0

Ich habe ein einfaches Problem, aber ich weiß nicht, wie man es löst, weil ich Funktoren in C++ nie verwendet habe.C++: Funktoren und Std :: Funktion für ein Noob

Ich mag so etwas tun (es ist nur ein Beispiel):

class MyClass 
{ 
    void applyFunction(myFunction); /* WRONG SYNTAX */ 
    double *_x; 
    unsigned int *_size; 
}; 

void MyClass::applyFunction(myFunction) /* WRONG SYNTAX */ 
{ 
    for (unsigned int i = 0; i < _size; ++i) 
     myFunction(_x[i], 10.); 
} 

class OtherClass 
{ 
    void myFunction1(double x, double lim); 
    void myFunction2(double x, double lim); 
    std::vector _v; 
}; 

void OtherClass::myFunction1(double x, double lim) 
{ 
    _v.clear(); 
    if (x > lim) 
     _v.push_back(x); 
} 

void OtherClass::myFunction2(double x, double lim) 
{ 
    _v.clear(); 
    if (x < lim) 
     _v.push_back(x); 
} 

int main() 
{ 
    MyClass myClass; 
    OtherClass otherClass; 
    myClass.applyFunction(otherClass.myFunction1); /* WRONG SYNTAX */ 
    std::cout<<otherClass._v.size()<<std::endl; 
    myClass.applyFunction(otherClass.myFunction2); /* WRONG SYNTAX */ 
    std::cout<<otherClass._v.size()<<std::endl; 
     return 0; 
} 

Was die korrekte Syntax verwenden functors/std :: Funktionen sein würde?

Vielen Dank!

+0

Was genau wollen Sie tun? Die Wikipedia-Seite zeigt typische Beispiele. – Pubby

+1

Sie haben viel zu viele Fehler in Ihrem Code. 'std :: vector _v',' double * _x; 'wird als' _x [i] 'verwendet,' unsigned int * _size; 'wird als' i <_size' und 'x> lim' usw. verwendet. –

Antwort

4

Ich nehme Sie bei Ihrem Wort, dass Sie Funktoren dafür verwenden möchten. Nur für grins, werde ich auch davon ausgehen, dass Sie das "richtig" machen wollen, nicht nur eine Syntax finden, die es kompilieren lässt (und wahrscheinlich laufen lässt, vielleicht tut, was Sie wollten).

In diesem Fall verfügt die Standardbibliothek bereits über Algorithmen, um vieles von dem zu unterstützen, was Sie gerade tun (besonders in C++ 11). Um die Daten, die einige Kriterien erfüllen, in einen Zielvektor zu kopieren, haben Sie std::copy_if (obwohl das in C++ 98/03 fehlt - müssen Sie den Sinn des Vergleichs umkehren und std::remove_copy_if verwenden).

Mit diesem wird der Code so etwas wie diese:

template <class T> 
class less_than { 
    T limit; 
public: 
    less_than(T lim) : limit(lim) {} 
    bool operator()(T const &val) { return val < limit; } 
}; 

std::copy_if(source.begin(), 
      source.end(), 
      std::back_inserter(target), 
      less_than<int>(10)); 

Wenn Sie jedoch haben C++ 11 zur Verfügung, ist es wahrscheinlich bequemes, ein Lambda zu verwenden, anstatt:

std::copy_if(source.begin(), 
      source.end(), 
      std::inserter(target), 
      [](int v) { return v < 10;}); 

Der Lambda ist im Grunde nur eine Möglichkeit, den Compiler dazu zu bringen, eine anonyme Funktorklasse für Sie zu generieren. Es gibt also keinen wirklichen Unterschied zwischen den beiden, aber das Lambda spart offensichtlich einiges an Tipparbeit.

Wenn Sie mit C++ 03 stecken, Sie im Grunde invertieren nur den Vergleich:

template <class T> 
class greater_than { 
    T limit; 
public: 
    bool operator()(T const &val) { 
     return val > limit; 
    } 
}; 

std::remove_copy_if(src.begin(), 
        src.end(), 
        std::back_inserter(dst), 
        greater_than(10)); 

Alternativ können Sie Ihre eigene schreiben konnte copy_if ziemlich leicht - es war links von C++ 98/03 meist durch Aufsicht, nicht weil es irgendetwas braucht, was die Sprache nicht bietet oder ähnliches (obwohl, wie ich mich erinnere, es schwierig sein kann, alle Randbedingungen genau richtig zu bekommen).

Für das, was es wert ist, ich sollte auch zu beachten, dass die Standard-Bibliothek hat std::less und std::greater, so dass die less_than und greater_than functors ich oben gegeben habe, sind nicht wirklich notwendig. Leider haben sie den Vergleich einfach nicht, so sie zu nutzen, wie wir hier zu tun sind, haben Sie std::bind1st oder std::bind2nd verwenden, um sie auf eine Konstante zu vergleichen zu erhalten:

std::remove_copy_if(src.begin(), 
        src.end(), 
        std::ostream_iterator<int>(std::cout, "\n"), 
        std::bind1st(std::less<int>(), 10)); 
1
void applyFunction(std::function<void(double, double)>); 
// ... 
applyFunction(std::bind(&OtherClass::myFunction1, &otherClass));