Zeiger auf eine Methode über typedef



  • Ich versuche gerade, in einer ABC definierte Memberfunktionen als Parameter in einer abgeleiteten Klasse zu übergeben, finde aber keine vernünftige Lösung.
    gegeben:

    //WVObject.hpp
    class WVObject
    {
    protected:
    	typedef bool (*EvalFun)(unsigned long);
    
    	bool evalA (unsigned long id) const;
    	bool evalB (unsigned long id) const;
    
    	template <class T>
    	T getVal (EvalFun fnctToEval) const
    	{
    		//hier der Zugriff auf die übergebene Methode
    		(*fnctToEval) (i);
    	}
    
    public:
    	//...
    };
    
    //WVKnoten.hpp
    class WVKnoten : public WVObject
    {
    }
    
    //WVKnoten.cpp
    void WVKnoten::parse ()
    {
    	//...
    	int res = getVal<float>(evalB); //hier liegt wahrscheinlich der Fehler
    }
    

    Wenn ich das so mache, dann sagt der Compiler

    WVKnoten.cpp(21): error C2248: "WVObject::evalB": Kein Zugriff auf protected Member, dessen Deklaration in der WVObject-Klasse erfolgte.
    WVKnoten.cpp(21): error C2664: 'T WVObject::getVal<float>(const std::string &,unsigned short,unsigned short,WVObject::EvalFun,bool,unsigned long) const': Konvertierung des Parameters 4 von 'bool (__thiscall WVObject::* )(const std::string &,unsigned long,const std::string &,const std::string &) const' in 'WVObject::EvalFun' nicht möglich

    Im Internet bin ich auch nicht schlauer geworden. Was mache ich falsch?



  • [Rewind] schrieb:

    Im Internet bin ich auch nicht schlauer geworden. Was mache ich falsch?

    Du mißachtest den Thread [url=http://www.c-plusplus.net/forum/304133]Den richtigen Code posten: reduziertes compilierbares Beispiel
    [/url]
    Dann sind sowohl evalA , als auch evalB Memberfunktionen, also mitnichten vom Typ EvalFun .

    Ich glaube das hier koennte eine Lösung sein.
    Änderungen markiert.

    class gadget{
    protected:
      typedef void(gadget::*fp)(); // hier
      void a(){}
      void b(){}
    public:
      void func(fp p){}
    };
    
    struct widget : gadget{
      gadget g;
      void func2(){
        g.func(&widget::a); // hier
      }
    };
    
    int main(){
    }
    

    Ich verstehe 11.4 [class.protected] dahingehend, dass der nested-name-specifier widget da hin muss(Z.13).



  • Danke, aber durch die Änderungen hat sich nichts an der Ausgabe geändert.
    Mir ist aufgefallen, dass du die Funktion nicht über dasimplizite this, sondern über ein Objekt der Basisklasse aufrufst. Hat das irgendeine Auswirkung?



  • [Rewind] schrieb:

    Mir ist aufgefallen, dass du die Funktion nicht über dasimplizite this, sondern über ein Objekt der Basisklasse aufrufst. Hat das irgendeine Auswirkung?

    Das ist - wie geschrieben - meine Interpretation von 11.4 im C++ Standard.

    11.4 Protected member access [class.protected]
    1 An additional access check beyond those described earlier in Clause 11 is applied when a non-static data member or non-static member function is a protected member of its naming class (11.2)115 As described earlier, access to a protected member is granted because the reference occurs in a friend or member of some class C. If the access is to form a pointer to member (5.3.1), the nested-name-specifier shall denote C or a class derived from C. All other accesses involve a (possibly implicit) object expression (5.2.5). In this case, the class of the object expression shall be C or a class derived from C.

    [Rewind] schrieb:

    Danke, aber durch die Änderungen hat sich nichts an der Ausgabe geändert.

    Dann wäre es jetzt wirklich an der Zeit ein minimales Beispiel zu bringen. Meins scheint ja das Problem nicht widerzuspiegeln.



  • https://ideone.com/KqqNKY
    Wie gesagt, das Problem könnten Zeile 7 und/oder 27 sein.

    #include <iostream>
    using namespace std;
    
    class WVObject
    {
    protected:
        typedef bool (*EvalFun)(unsigned long);
    
        bool evalA (unsigned long id) const { return true; }
        bool evalB (unsigned long id) const { return false; }
    
        bool test (EvalFun fnctToEval) const
        {
            //hier der Zugriff auf die übergebene Methode
            bool res = (*fnctToEval) (4);
            return res;
        }
    
    public:
        virtual void parse() = 0;
    };
    
    //WVKnoten.hpp
    class WVKnoten : public WVObject
    {
    public:
    	void parse () { cout << test(&WVObject::evalA); }
    };
    
    int main() {
    	WVKnoten obj;
    	obj.parse();
    	return 0;
    }
    

  • Mod

    #include <iostream>
    using namespace std;
    
    class WVObject
    {
    protected:
    	typedef bool ( WVObject::* EvalFun ) ( unsigned long ) const; // Das hier muss ein Zeiger auf eine Memberfunktion sein
    
    	bool evalA ( unsigned long id ) const { return true; }
    	bool evalB ( unsigned long id ) const { return false; }
    
    	bool test ( EvalFun fnctToEval )
    	{
    		bool res = (this->*fnctToEval)( 4 ); // Hier muss die entsprechende Syntax verwendet werden
    		return res;
    	}
    
    public:
    	virtual void parse() = 0;
    };
    
    class WVKnoten : public WVObject
    {
    public:
    	void parse () { cout << test( &WVKnoten::evalA ); /* Es muss WVKnoten sein*/ }
    };
    
    int main()
    {
    	WVKnoten obj;
    	obj.parse();
    }
    


  • Super, Arcoth, danke! Problem gelöst.


Anmelden zum Antworten