2016-08-20 2 views
3

Ziemlich neu in C++. Angenommen, ich habe eine Klasse:C++ Externe Funktion mit Zeiger, um als Parameter zu fungieren, innerhalb einer Klasse mit einer Elementfunktion

class A 
{ 
private: 
    double m_x, m_y; 
public: 
    A(double x, double y): m_x {x} 
    { 
     m_y = extF(m_x, y, *intF); 
    } 

    double intF(double x) { return 2*x; } 
}; 

Und es macht die Verwendung einer externen globalen Funktion, an anderer Stelle definiert:

double extF(double x, double y, std::function<double(double)> f) 
{ 
    if (x*y < 0) 
     return f(x); 
    else 
     return f(y); 
} 

Formeln gefälschte sind. Dies kompiliert nicht. Ich versuchte einfach intF, A::*intF, &A::intF, sogar einige unorthodoxe Kombinationen, aber das ist nur raten. Das Problem ist, dass die Klasse A nicht die einzige ist, die die globale externe Funktion verwendet, und sie sollte zur Laufzeit für den Benutzer auswählbar sein. Suchanfragen ergaben einige Antworten, die besagen, dass es nicht möglich ist, einen Zeiger auf eine Elementfunktion wie diese zu setzen, da sie Instanziierung (?) Benötigt, aber ich habe keine Lösungen gefunden. Kann das gemacht werden? Wenn ja, wie?


Edit: Weitere Frage: Wie kann der Zeiger auf Member-Funktion, wenn die Funktion const double f(...) const ist Mitglied getan werden?

+0

Machen Sie die statische Memberfunktion "intF", wenn sie nicht auf Member der Klasse zugreift. – songyuanyao

+0

@songyuanyao Leider tut es das. Wenn ich wüsste, dass das ein Problem ist, hätte ich den Code so geändert, dass er angezeigt wird. –

+0

@aconcernedcitizen Nicht deine Schuld, sondern meine. Ich ging zuerst OT, löschen wir diese Kommentare. –

Antwort

3

Eine Variante ist nur Lambda zu verwenden:

class A 
{ 
private: 
    double m_x, m_y; 
public: 
    A(double x, double y): m_x {x} 
    { 
     m_y = extF(m_x, y, [&](double d){ return intF(d);}); 
    } 

    double intF(double x) { return 2*x; } 
}; 

Eine andere Variante ist Lambda zu verwenden und std::mem_fn (den Rest Code Ihrer Klasse weggelassen):

A(double x, double y): m_x {x} 
{ 
    auto fn = std::mem_fn(&A::intF); 
    m_y = extF(m_x, y, [&](double d) {return fn(this, d);}); 
} 

Und Schließlich können Sie lambdas loswerden, wenn Sie bind den Objektparameter des Mitglieds Funktionszeiger:

A(double x, double y): m_x {x} 
{ 
    auto fn1 = std::bind(std::mem_fn(&A::intF), this, std::placeholders::_1); 
    m_y = extF(m_x, y, fn1); 
} 

Alle diese arbeiten auch mit konstanten Elementfunktionen.

+0

Vielen Dank, beide (@songuyanyao und Sie), für Ihre Antworten. Ich kenne die 'std :: mem_fn' und' std :: bind' noch nicht. Ich werde jetzt über sie lesen. –

2

Sie könnten std::bind verwenden, um die Elementfunktion zu binden.

A(double x, double y): m_x {x} 
{ 
    using namespace std::placeholders; 
    m_y = extF(m_x, y, std::bind(&A::intF, this, _1)); 
} 

Oder verwenden Sie eine lambda.

A(double x, double y): m_x {x} 
{ 
    m_y = extF(m_x, y, [this](double d) { return intF(d); }); 
} 

BTW: Es funktioniert auch gut mit const Member-Funktion, die hier keine Rolle spielt.

LIVE

Verwandte Themen