Functor, Functionszeiger



  • Guten Tag,

    habe mir schon sehr viele Programmtexte angesehen mit Funktionsobjekten (Funktoren).

    Jetzt war meine Idee, daß ich eine Klasse für einen functor anlege und dieses Object in einer anderen Klasse verwende...

    #include <iostream>
    
    class Functor
    {
    protected:
      // function to call a memberfunction to display the data contend of a variable
      std::string (*functionptr)();
    public:
      Functor();
      std::string operator()(std::string (*functionptr)());
    };
    
    Functor::Functor():functionptr(0) 
    {}
    
    std::string Functor::operator()(std::string (*fptr)())
    {
      functionptr=fptr;
    }
    
    class address
    {
    protected:
      std::string firstName;
      std::string secondName;
    
      std::string (address::*pfn)();     // this is a functionpointer with the name pfn
    
    public:
      Functor f_pfn;
      address(std::string _firstName="mein", std::string _secondName="Name");
      std::string getfirstName();
      std::string getsecondName();
      void ausgabeinit();
      void execute();
    };
    
    address::address(std::string vname, std::string nname):firstName(vname), secondName(nname), pfn(0)
    {
    	std::cout << "\nconstructor pfn: " << pfn << std::endl;
    }
    
    std::string address::getfirstName()
    {
      return firstName;
    }
    
    std::string address::getsecondName()
    {
      return secondName;
    }
    
    void address::ausgabeinit()
    {
    	pfn=&address::getfirstName;
    	std::cout << "\nausgabeinit() pfn: " << pfn << std::endl;
    	std::cout << (this->*pfn)() << std::endl;
    }
    
    void address::execute()
    {
    	std::cout << "\naddress::execute(): " << (this->*pfn)();
    }
    
    int main()
    {
      Functor malso;
      address icke;
      std::cout << "Vorname: " << icke.getfirstName() << std::endl;
      icke.ausgabeinit();
      icke.execute();
      std::cout << "\nicke(getsecondName()): " << icke.(address::getsecondName()) << std::endl;
      return 0;
    }
    

    als fehlermeldung kommt:

    g++ -o mitfunktor functorclass.cc 
    functorclass.cc: In Funktion »int main()«:
    functorclass.cc:72:52: Fehler: expected unqualified-id before »(« token
    functorclass.cc:72:76: Fehler: Elementfunktion »std::string address::getsecondName()« kann nicht ohne Objekt aufgerufen werden
    

    was muß ich tun damit ich den operator() des functors aufrufen kann? Oder besser wo mache ich den Fehler?

    der functor ist ein public-element und müsste aufrufbar sein, ein object habe ich doch auch gebastelt... 😕



  • Kennst du std::function?



  • Nach icke muss der Punkt weg. Und nach address::getSecondName die Klammern. Außerdem geht das nicht, da address::getsecondName eine Memberfunktion ist, die Funktion operator() nimmt aber einen Funktionpointer, keinen Memberfunktionpointer.



  • 😮 Versteh ich richtig, obwohl Functor ein Attribut von address ist, darf ich nicht auf die memberfunktionen von address zugreifen?

    nein, std::function habe ich zwar schonmal im Netz gelesen, aber kennen tu ich's nicht.

    Bin absoluter Anfänger und versuche die "logischen" Grundlagen zu verstehen, damit ich weiß was ich mache wenn ich ein Programm schreibe...

    erst mal vielen dank, dann versuch ich's mal mit deinem Tip



  • Außerdem, wo benutzt du den Funktor überhaupt 😕



  • In dem Code versuche ich im "main" den Functor zu benutzen... dachte ich da ja die class address keinen operator() hat... wäre es ein Lösung in address einen operator() einzubauen der die verschiedenen Ausbage- get-funktionen aufruft 😡



  • Erst mal den Code

    bool Person::SetFunctionsPtr()
    {
      bool (Person::*SetFunctions[PERSON_ATTRIBUTES])(std::string) = {&Person::SetPersonID,  &Person::SetAddress, &Person::SetFirstName, &Person::SetSecondName, &Person::SetNameAffix, &Person::SetTitle};
    
      std::string (Person::*GetFunctions[PERSON_ATTRIBUTES])() const={&Person::GetPersonID, &Person::GetSecondName, &Person::GetFirstName, &Person::GetNameAffix, &Person::GetAddress, &Person::GetTitle};
    
      if(SetFunctions && GetFunctions)
        {
          std::cout << "SetFunctions: " << SetFunctions << std::endl;
          std::cout << "GetFunctions: " << GetFunctions << std::endl;
    
        return true;
        }
      else 
        return false;
    }
    
    bool Person::SetPerson()
    {
      std::cout << "In SetPerson SetFunctions: " << Person::SetFunctions << std::endl;
          std::cout << "In SetPerson GetFunctions: " << GetFunctions << std::endl;
    }
    
    #include "person.h"
    
    int main()
    {
    	Person probemensch;
    
    	probemensch.SetPerson();
    
    	return 0;
    }
    

    Kurze Erläuterung meiner Idee: Die Zeiger sind Members der Klasse person, also, so dachte ich, von allen Methoden aufrufbar. Da ich diese member öfter benutzen will habe ich sie in der klasse implementiert. Im Konstruktor bekomme ich auch addressen von den Zeigern angezeigt, aber dann in der methode SetPerson() folgendes:

    enklasse/src$ ../verwaltung 
    SetFunctions: 0xbf8ab990
    GetFunctions: 0xbf8ab9c0
    
    Weiter geht's mit irgendeiner Taste...
    
    In SetPerson SetFunctions: 0xbf8abcbc
    In SetPerson GetFunctions: 0xbf8abcbc
    

    Also denke ich, daß ich irgendwo einen Fehler in der syntax/logik habe da auch mit &SetFunctions oder *SetFunctions nicht die adresse angezeigt wird in SetPerson wie in dem Konstruktor...

    Leider finde ich keine Möglichkeit, bzw. habe keine Idee wie ich den zeiger aufrufen muß damit die gewünschte "Adresse" bzw. die Funktion hinter der Adresse ausgeführt wird...



  • Was soll das denn alles? Worum geht's dir? Was hat da ein Elementfunktionszeiger in der Klasse address zu suchen? Warum hast du ein #include "person.h" hinter den Definitionen von Sachen aus der Person-Klasse? Ich glaube, du machst alles viel komplizierter als nötig ...

    #include <iostream>
    #include <string>
    
    struct address
    {
      std::string firstname;
      std::string secondname;
    };
    
    typedef std::string address::*amemptr;
    
    int main()
    {
      using namespace std;
      address a = { "Hans", "Wurst" };
      amemptr m = &address::firstname;
      cout << (a.*m) << endl;
      m = &address::secondname;
      cout << (a.*m) << endl;
    }
    


  • Nun, ich will einen Funktionzeiger in meiner Klasse haben um dann über eine Zahl die notwendige Funktion zur Ausgabe bzw. Veränderung des Wertes der in der Variabelen steht zu verändern...

    Weil ich "träge" bin dachte ich es wäre am einfachsten wenn ich einen Zeiger auf die Funktionen deklariere und definiere, damit ich sie aufrufen kann, aber ich kriegs nicht hin 😞



  • thepower schrieb:

    um dann über eine Zahl die notwendige Funktion zur Ausgabe bzw. Veränderung des Wertes der in der Variabelen steht zu verändern...

    Warum? Das erschließt sich mir nicht.



  • ...könnte sein, daß ich falsch liege, aber ich habe im Moment folgendes im Header stehen:

    // Header for class person
    // 30.05.2012
    
    #ifndef _PERSON_H
    #define _PERSON_H
    
    #ifndef STRING_H
    #include <string>
    #endif
    
    #ifndef _GLIBCXX_FSTREAM
    #include <fstream>
    #endif
    
    class Person
    {
    protected:
      // static members
      static unsigned int NumberOfPersons;
      static const int PERSON_ATTRIBUTES;
    
      // static methods
      // functions to Set/Get the allowed values of IDs
      static unsigned int SetNumberOfPersons();
      static unsigned int GetNumberOfPersons();
    
      // Tools to make functions usable
      unsigned int CountMembersFile();
    
      // Datamembers of person: PersonID:second name:first name:name affix (jun. or something else):Addressing:title (Dr. or so on)
      unsigned int PersonID;
      std::string SecondName;
      std::string FirstName;
      std::string NameAffix;
      std::string Address;
      std::string Title;
    
      // Filename in which the data is stored
      std::string FileNamePerson;
    
      // Filepointers
      std::fstream InFilePersons;      // Put data in File FileNamePerson
      std::fstream OutFilePersons;     // Get data from File FileNamePerson
    
      // Pointer to the Set-functions Set to 0 in constructor
      bool(Person::*SetFunctions[])(std::string);
    
      // Pointer to the Get-functions Set to 0 in constructor
      std::string (Person::*GetFunctions[])() const;
    
    public:
      // Constructor with default values
      Person( unsigned int _PersonID=0,
    	  std::string _SecondName="Scheidt",
    	  std::string _FirstName="Marianne",
    	  std::string _NameAffix="jun.",
    	  std::string _Address="Herr",
    	  std::string _Title="",
    	  std::string _FileNamePerson="customerNames.dat");
    
      // Destructor "virtual" if it is needed in derived classes
      virtual ~Person()
      {}
    
      // Set values of the functionpointers
      virtual bool SetFunctionsptr();
    #if 0
      // Set values of a whole person
      virtual bool SetPerson();
    
      // Set values of a person
      virtual bool SetPersonID(std::string _personID);
      virtual bool SetSecondName(std::string _in);
      virtual bool SetFirstName(std::string _in);
      virtual bool SetNameAffix(std::string _in);
      virtual bool SetAddress(std::string _in);
      virtual bool SetTitle(std::string _in);
    
      // function to change the Set values of a variable
      bool ChangeValues(int selection); // selection is the number of the choosen variable
    
      //Get-functions to "use" the variable values of Person
      virtual std::string GetPersonID() const;
      virtual std::string GetSecondName() const;
      virtual std::string GetFirstName() const;
      virtual std::string GetNameAffix() const;
      virtual std::string GetAddress() const;
      virtual std::string GetTitle() const;
    
      // Function to Set the Menue which the users need to run the application
      virtual void Menue();
    
      // Function to write the Person to in form:
      // Person Nummer: PersonID
      // Anrede: Address Title: Dr. med.
      // Vorname: FirstName 
      // Nachname: SecondName
      // Anhang: NameAffix
      virtual void Output() const;
    
      // Function to read the file with the stored Persones
      // std::string filename is the name of the file in which the 
      // Persones are stored
      bool ReadFile(std::string filename);
    #endif
    };
    #endif
    

    immper wenn ich eine set- oder getfunction benögte rufe ich sie mit ihrem namen auf, wenn ich alle brauche rufe ich 6 mal die namen von set- oder get- auf... wenn ich das ganze in ein pointerarray lege kann ich mit for(int i = 0; i < sizeof(pointerarray); ++9) die aufrufe vereinfachen... dachte ich


Anmelden zum Antworten