Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Eigene Funktion für eine Instanz

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
02.07.2008, 21:37 Uhr
Suba Esel



Ist sowas vom Prinzip her möglich? Ich dachte da an ungefähr sowas:


Code:
class Blabla
{
Blabla(funktion) {}
void Do()
{
// hier jetzt die Funktion, die beim Konstruktor übergeben wurde, aufrufen
}
};



Sprich, wenn ich zum Beispiel ein Menü hab, wo ich eine Klasse für die Buttons hab, dann soll ja bei einem Klick auf einen Button immer etwas anderes passieren. Wenn das Menü groß wird, wird das ziemlich umständlich, das einzeln zu machen - man kann ja noch nicht einmal mit einer Forschleife durchgehen.


Falls einer eine Möglichkeit weiß, die nicht ZU kompliziert ist... ansonsten muss ich das Ganze umarbeiten.
--
Simon
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
02.07.2008, 22:42 Uhr
CppProgrammer



Im Prinzip ja. Stichwort Funktionspointer.

EDIT:
Hatte gerade nichts zu tun. Daher hab ich dir das ganze mal schnell exemplarisch aufgezeigt.


C++:
#include <iostream>
using namespace std;

class Blabla
{
public:
    // Unser Konstruktor
    Blabla( void(*ptr2Func)(int, int) ){
        m_ptr2Func = ptr2Func;
    }

    void Do(){
        // hier jetzt die Funktion, die beim Konstruktor übergeben wurde, aufrufen
        (*m_ptr2Func)(1, 2);
    }

private:
    // Hier unser Funktionspointer als Membervariable der Klasse
    void(*m_ptr2Func)(int, int);

};

void printAddition(int a, int b)
{
    cout << a + b << endl;
}

void printSubtraction(int a, int b)
{
    cout << a - b << endl;
}

int main(int argc, char* argv[])
{
    Blabla myclass1(&printAddition);
    myclass1.Do(); // Hier wird uns jetzt die SUMME von 1 und 2 ausgegeben

    Blabla myclass2(&printSubtraction);
    myclass2.Do(); // Und hier bekommen wird jetzt die DIFFERENZ von 1 und 2 ausgegeben

    return 0;
}


Dieser Post wurde am 02.07.2008 um 23:03 Uhr von CppProgrammer editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
03.07.2008, 00:33 Uhr
kronos
Quotenfisch
(Operator)


In C++ würde man vermutlich Funktionobjekte bevorzugen, also eine Funktions-Basisklasse mit einer abstrakten Methode definieren, die du dann in verschiedenen abgeleiteten Klassen unterschiedlich ausimplementieren kannst. Wenn du das ganze mit operator() machst, hast du syntaktisch keinen Unterschied mehr in der Verwendung aber mehr Typsicherheit oder so'n Schrott den keiner braucht und überhaupt gehört Java doch verboten...
--
main($)??<-$<='?'>>2?main($-!!putchar(
(("$;99M?GD??(??/x0d??/a:???;a"+'?'/4)
??($??)+'?'/3-2-1+$%2)??''?')):'?';??>
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
03.07.2008, 13:04 Uhr
Suba Esel



@CppProgrammer: Danke, das ist genau das, was ich gesucht hatte.
@Kronos: Sorry, dich hab ich irgendwie nicht ganz verstanden. Meinst du das so, dass man dann für jeden "Typ" Button eine eigene Klasse erstellst? Dann ist das IMHO genauso umständlich wie das, was ich jetzt habe.

Nochmal zur Verdeutlichung, was ich meine:

menu.hpp:

C++:
class Menu : public Work
{
public:
    Menu();
    virtual void Step();
    virtual void Draw();
private:
    class ButtonInfo
    {
    public:
        ButtonInfo(std::string, std::string, int, int);
        bool IsClicked();
        void Draw();
    private:
        std::string texture_, mouseover_;
        int height_, width_, posX_, posY_;
        bool clicked;
    };
    std::vector<ButtonInfo> ButtonInformation;
};




menu.cpp:

C++:
Menu::Menu()
{
    ButtonInformation.push_back("spiel_starten.PNG", "spiel_starten_mouseover.PNG", 512, 0);
    ButtonInformation.push_back(ButtonInfo("spiel_beenden.PNG", "spiel_beenden_mouseover.PNG", 512, 768 - jngl::Height("spiel_beenden.PNG")));
}

void Menu::Step()
{
    // so, diese Stelle meine ich - das ist so etwas blöde.
    if(ButtonInformation[0].IsClicked())
    {
        Procedure::Handle().SetWork(boost::shared_ptr<Game>(new Game));
    }

    if(ButtonInformation[1].IsClicked())
    {
        jngl::Quit();
    }
}

void Menu::Draw()
{
    for(int i = 0; i < ButtonInformation.size(); ++i)
    {
        ButtonInformation[i].Draw();
    }
}

bool Menu::ButtonInfo::IsClicked()
{
    return clicked;
}

void Menu::ButtonInfo::Draw()
{
    clicked = jngl::Button(texture_, posX_, posY_, mouseover_);
}

Menu::ButtonInfo::ButtonInfo(std::string texture, std::string mouseover, int posX, int posY) : texture_(texture), mouseover_(mouseover), posX_(posX), posY_(posY)
{
    height_ = jngl::Height(texture_);
    width_ = jngl::Width(texture_);
    clicked = false;
}




jngl ist eine OpenGl-Graphiklibrary von nem Freund von mir, jngl::Button zeichnet den Button und gibt gleichzeitig zurück, ob er geklickt wird.

EDIT: Die verlinkte Version ist nicht die ganz aktuelle, diese findet sich hier.
--
Simon

Dieser Post wurde am 03.07.2008 um 13:09 Uhr von Suba Esel editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
03.07.2008, 13:39 Uhr
Suba Esel



Hm, hakt immernoch irgendwo.

Code:
ButtonInfo(std::string, std::string, int, int, void(*PtrFunc)());
//.....
ButtonInformation.push_back(ButtonInfo("spiel_beenden.PNG", "spiel_beenden_mouseover.PNG", 512 , 0, &jngl::Quit)); // funktioniert
ButtonInformation.push_back(ButtonInfo("spiel_starten.PNG", "spiel_starten_mouseover.PNG", 512 , 0, &Procedure::Handle().SetWork(boost::shared_ptr<Game>(new Game)))); // hier sagt er mir: "error: non-lvalue in unary `&'"



Liegt das daran, dass die Funktion einen Parameter hat?
--
Simon

Dieser Post wurde am 03.07.2008 um 13:39 Uhr von Suba Esel editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
03.07.2008, 14:22 Uhr
kronos
Quotenfisch
(Operator)


Du versuchst hier, die Addresse eines Rückgabewertes (von SetWork) zu nehmen, das geht nich.
Was willst denn da machen? Was gibt die Funktion zurück?


Zum Thema Funktionsobjekte:
http://en.wikipedia.org/wiki/Function_object
www.inquiry.com/techtips/cpp_pro/10min/10min0100.asp

Wenn du die wo's geht als template-Argumente verwendest wird dein code ein bischen schneller...
--
main($)??<-$<='?'>>2?main($-!!putchar(
(("$;99M?GD??(??/x0d??/a:???;a"+'?'/4)
??($??)+'?'/3-2-1+$%2)??''?')):'?';??>

Dieser Post wurde am 03.07.2008 um 14:23 Uhr von kronos editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
03.07.2008, 17:00 Uhr
Suba Esel



Okay, noch mal von vorne... hab das etwas schlecht beschrieben.

Ich möchte, dass bei jedem Button etwas anderes gemacht wird (logischerweise). Bei Button 1 soll zum Beispiel jngl::Quit() ausgeführt werden, bei Button 2 Procedure::Handle().SetWork(boost::shared_ptr<Game>(new Game)). Wenn ich das so wie oben abfrage, bekomm ich aber Probleme - falls ich das in anderer Reihenfolge in den Vector packe, macht der Blödsinn.

Procedure::Handle().SetWork(boost::shared_ptr<Game>(new Game) gibt void zurück und setzt einfach nur, dass das Aktuelle sozusagen ein Game ist, nicht ein Menü (wie vorher). Ist etwas kompliziert zu erklären - ich habs auch noch nicht ganz verstanden, wir programmieren das in einer AG in der Schule.

Mein Problem ist jetzt, dass ich es nicht hinbekomme, eine Funktion mit Parametern zu übergeben.
--
Simon

Dieser Post wurde am 03.07.2008 um 17:32 Uhr von Suba Esel editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
03.07.2008, 17:32 Uhr
0xdeadbeef
Gott
(Operator)


C++ kann von Haus aus keine Lambda-Operationen, um eine Adapterfunktion wirst du also nicht herumkommen. Etwa in der Art:

C++:
void SetWorkToGame() {
  Procedure::Handle().SetWork(boost::shared_ptr<Game>(new Game)
}

// ...

ButtonInformation.push_back(ButtonInfo("spiel_starten.PNG", "spiel_starten_mouseover.PNG", 512 , 0, &SetWorkToGame)));


Mit einem Haufen Operatorüberladungen mag etwas derartiges auch on-the-fly möglich sein, ich würde mir dafür mal Boost.Lambda ankucken.

Nachtrag:
...oder besser, Boost.Bind.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 03.07.2008 um 17:42 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
03.07.2008, 18:57 Uhr
Suba Esel



Ok, danke... hab das jetzt so gemacht, wie du es vorgeschlagen hast.

Auch an die anderen noch mal Dankeschön!
--
Simon
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: