2016-05-10 13 views
0

Ich machte ein einfaches Beispiel, um die Wechselwirkung von Boost Bind mit abgeleiteten Klassen zu testen.Boost Mem_fn und zugreifende Member-Funktion der abgeleiteten Klasse

Ich habe zwei Unterklassen mit verschiedenen getarea-Funktionen erstellt. Ich erwartete

g1 = boost::bind(boost::mem_fn(&Shape::getarea), Rec) 

den Bereich Rectangle (10,20) zu drucken, sondern es gedruckt '1'. Ich bekomme das gleiche, wenn ich stattdessen Rectangle::getarea schreibe. Es druckt das selbe auch wenn ich andere Funktionen zB eingib. Mitglied von Rectangle

double sum(double h,double w){return h+w; } 

und

g1 = boost::bind(boost::mem_fn(&Rectangle::sum), Rec,2,3) 

Frage 1 verwenden:? Warum sie zurückkehren '1' Ist das eine Standardantwort für Fehler?

Mein zweites Problem besteht darin, dasselbe mit g2 zu tun, aber jetzt wird Rec durch ** iter ersetzt, d. H. Ein Objekt eines abgeleiteten Klassentyps aus einer Liste von Objekten. Da getArea ein virtuelles fcn ist, wenn ich die oben arbeiten sie bekommen sollte in Ordnung sein, nur schreiben:

g2= boost::bind(boost::mem_fn(& Shape::getarea , &(**iter)); 

Frage 2: Aber ich frage mich, ob es einen Weg gibt, die von classtype zurückzukehren ** iter zB. classof (** iter) und dann in g2 setzen heißt

g2= boost::bind(boost::mem_fn(& classof(**iter)::getarea , &(**iter)); 

Wenn ich g2 lief durch Form zu schreiben :: getArea, ich habe '1' wieder für alle iter.

#include <memory> 
    #include <vector> 
    #include <string> 
    #include <iostream> 
    #include <sstream> 
    #include <boost/bind.hpp> 
    using namespace std; 

    class Shape { 
     public:  
      Shape(double h, double w) :height(h), width(w) {}; 
      virtual double getarea() = 0; 
      double height; 
      double width; }; 

     class Rectangle: public Shape { 
     public: 
      Rectangle(double h, double w): Shape(h,w) {}; 
      double getarea() override { return height*width; } }; 

     class Triangle : public Shape { 
     public: 
       Triangle(double h, double w) :Shape(h,w) {}; 
       double getarea() { return height*width*0.5; }}; 

     int main() { 
     //create objects 
      Rectangle Rec(10, 20); 
      Triangle Tri(2, 3); 


     //create boost bind function 
      boost::function<double(double, double)> g1; 
      g1 = boost::bind(boost::mem_fn(&Shape::getarea), Rec); 
    //print area and g 
      cout << Rec.getarea()<<" should be equal to " << g1<< '\n'; 


    //create list 
      vector<shared_ptr<Shape>> Plist; 
      Plist.push_back(make_shared<Rectangle>(Rec)); 
      Plist.push_back(make_shared<Triangle>(Tri)); 


     //print each element from the vector list 

     for (auto iter = Plist.begin(); iter != Plist.end(); iter ++) { 

       boost::function<double(double, double)> g2; 

       g2= boost::bind(boost::mem_fn(& .... , &(**iter)); 

     //where in dots we need Classtype_of_**iter::getarea 

      cout << (**iter).getarea()<<"should be equal to " << g2<< '\n'; 

     } 


     } 

Antwort

0

Sie ... vergessen, die Funktionen aufzurufen ...

for (auto iter = Plist.begin(); iter != Plist.end(); iter++) { 
    boost::function<double()> g2; 
    g2 = boost::bind(&Shape::getarea, iter->get()); 
    cout << (*iter)->getarea() << " should be equal to " << g2() << '\n'; 
} 

Was Sie gesehen haben, was die implizite Konvertierung (http://www.boost.org/doc/libs/1_60_0/doc/html/boost/function.html#idm45507164686720-bb)

Hinweis Bool auch fixiert ich die Unterschrift von g1 und g2: Live On Coliru.

Einige weitere Verbesserungen (die Notwendigkeit der g2 in der Schleife entfernen?):

auto getarea = boost::mem_fn(&Shape::getarea); 
for (auto iter = Plist.begin(); iter != Plist.end(); iter++) { 
    cout << (*iter)->getarea() << " should be equal to " << getarea(**iter) << '\n'; 
} 

Oder in der Tat in C++ 11:

for (auto& s : Plist) 
    cout << s->getarea() << " should be equal to " << getarea(*s) << '\n'; 

Zu diesem Zeitpunkt würden Sie frage mich, warum du diesen Accessor hast, wenn du nur das Mitglied benutzen kannst.