this* pointer: Selbst bestimmen, als welches objekt eine funktion aufgerufen wird... ?



  • lk schrieb:

    Sollte ich dann boost::bind(&MOD::mow, _1, this) aufrufen? Für zwei Parameter dann _1, _2 ?

    Nein, boost::bind(&MOD::mow, this, _1 ).



  • lk schrieb:

    Tachyon schrieb:

    lk schrieb:

    [...]Und virtuelle funktionen will ich auch nicht, da die etwas langsamer sind....

    Langsamer als was? Als ein ähnlicher Mechanismus von Dir selbst gebastelt? Wohl kaum. Für Plugins braucht man wohldefinierte Interfaces. Und dafür bieten sich unter C++ Klassen mit rein virtuellen Funktionen an.

    Ich will ja nicht direkt Plugins machen.

    Virtuelle funktionen sind einen ganz kleinen tacken langsamer als normale nicht-virtuelle funktionen. Ich werde auch viele funktionen in den plugins aufrufen, sehr oft...

    so what... Lies Dich mal in das Thema: "Premature Optimizing" ein, denn genau das machst Du gerade. Du versuchst ein etabiliertes, optimiertes System (virtuelle Funktion) durch etwas ähnliches zu ersetzen was unterm Strich eher langsamer als schneller sein wird. Abgesehen davon, selbst wenn der Aufruf einer virtuellen Funktion langsamer ist, so macht das vielleicht 0.000001% Deiner Rechnerperformance aus. Optimier lieber erstmal an anderen Stellen die auch eine meßbare Auswirkung auf die Performance haben.



  • Dynamic Binding geht eben über eine Indirektion. Wenn bei dem was du vorhast der Overhead dieser zusätzlichen Indirektion zu groß ist dann kannst du schlicht und einfach kein dynamic Binding verwenden, denn dieser Overhead ist rein prinzipieller Natur und hat nichts mit irgendeiner Ineffizienz in der Implementierung von virtuellen Funktionen zu tun. Was auch immer du bastelst wirst du diesen Overhead nicht loswerden. Wenn du dir ein Ersatzsystem für virtuelle Funktionen baust dann wird dieses System immer noch eine Indirektionsschicht brauchen. Der einzige Unterschied ist am Ende nur dass du beim selbst gebastelten System deine Funktionspointer selbst verwaltest und bei virtuellen Funktionen der Compiler das für dich übernimmt. Der Overhead liegt aber in der Natur der Sache und ist daher in deinem System genauso drin, auch wenn du das per Hand in Assembler schreibst ändert sich da nix dran.

    Die Aussage dass virtuelle Funktionen langsam sind ist jedenfalls vollkommen Sinnlos.



  • loks schrieb:

    so what... Lies Dich mal in das Thema: "Premature Optimizing" ein, denn genau das machst Du gerade. Du versuchst ein etabiliertes, optimiertes System (virtuelle Funktion) durch etwas ähnliches zu ersetzen was unterm Strich eher langsamer als schneller sein wird. Abgesehen davon, selbst wenn der Aufruf einer virtuellen Funktion langsamer ist, so macht das vielleicht 0.000001% Deiner Rechnerperformance aus. Optimier lieber erstmal an anderen Stellen die auch eine meßbare Auswirkung auf die Performance haben.

    Ein anderes Problem wäre, dass ich dann 2 zusätzliche klassen für jede klasse machen müsste. Übrigens hab ichs gerade hingekriegt...

    Ein schwacher Punkt wird wohl Baz::assign(..) sein... 😞

    Mein Code jetzt:
    (in die main() funktion gucken 😃 )

    class Foo
    {
    public:
        typedef function<int(int)> Func;
        typedef pair<string, Func > FEntry;
        typedef vector<FEntry> FList;
    
        //typedef int(Foo::* F)(int); // one static function
        //typedef vector< F > FL; // list of all of them
    
        virtual FList* getFuncs() = 0;
    };
    
    class Bar : public Foo
    {
    private:
        int data;
    
    public:
        virtual FList* getFuncs()
        {
            FList* list = new FList();
    
            #define ENTRY(x,y) list->push_back(std::make_pair( string( x ) , boost::bind( &Bar:: y , this, _1 ) ));
    
            list->push_back( std::make_pair(string("mow"), boost::bind(&Bar::mow, this, _1) ) );
            list->push_back( std::make_pair(string("sub"), boost::bind(&Bar::sub, this, _1) ) );
    
            // hehehe :)
            ENTRY("set", set);
            ENTRY("get", get);
    
            /*
             *   i = std::make_pair("foo", std::bind(&init::foo, this));
             * ++i = std::make_pair("bar", std::bind(&init::bar, this));
             * */
    
            // list->push_back( (FEntry)make_pair( "mow", boost::bind(&Bar::mow, 435, this) ));
    
            //ENTRY("Sub", sub);
    
            return list;
        }
    
        int set(int val)
        {
            data = val;
            return val;
        }
    
        int get (int dummy)
        {
            return data;
        }
    
        int mow(int in)
        {
            return in * 2;
        }
    
        int sub(int in)
        {
            return in - 100;
        }
    };
    
    struct Baz
    {
        typedef Foo::Func f;
    
        int assign(Foo* foo)
        {
            Foo::FList *list = foo->getFuncs();
            Foo::FEntry cur;
    
            //cout << "Baz::assign] list = " << list << endl;
    
            for (int i=0; i<list->size(); i++)
            {
                // switch mit strings o.O ?
    
                cur = list->at(i);
    
                //cout << "Baz::assign - for] cur.1=\"" << cur.first << " &cur.2=" << &cur.second << endl;
    
                if (!cur.first.compare("mow")) {
                    mow = cur.second;
                    continue;
                } else if (!cur.first.compare("sub")) {
                    sub = cur.second;
                    continue;
                } else if (!cur.first.compare("set")) {
                    set = cur.second;
                    continue;
                } else if (!cur.first.compare("get")) {
                    get = cur.second;
                    continue;
                }
                cout << "Baz::assign - for] Pointless function: " << cur.first << endl; // keine Übereinstimmung gefunden
            }
            return 0;
        }
    
        f mow;
        f sub;
        f set;
        f get;
    };
    
    int main()
    {
        Foo *ptr = new Bar(); // hier würde eigentlich eine funktion aus der Dynamischen bibliothek
        // aufgerufen werden: make();
    
        /*
        Foo::FList *flist = ptr->getFuncs();
        Foo::FEntry e_mow = flist->at(1);
        Foo::Func mow = e_mow.second;
    
        Foo::Func set = flist->at(2).second;
        Foo::Func get = flist->at(3).second;
    
        cout << set(352) << endl;
        cout << get(0) << endl;
        */
    
        Baz *bar = new Baz(); // "pseudo klasse"
    
        bar->assign(ptr);
    
        bar->set(372);
        cout << bar->get(0) << endl;
    
        return 0;
    }
    

Anmelden zum Antworten