Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

PD

unregistriert

1

13.10.2004, 20:28

Templates ohne Übergabewert

Sooo... ich hab bisher noch net viel mit templates am Hut gehabt. Daher möchte ich gerne wissen ob es eine möglichkeit gibt ne Funktion als Template zu machen ohne Übergabewerte ^^ Der grund ist das ich momentan ne Funktion hat die nen void pointer zurück gibt weil eben nicht feststeht worauf der zeigt um das flexibel zu halten (worauf er zeigt wird durch nen string festgelegt). Das prob ist das ich nun den rückgabe wert immer casten muss um ihn richtig zu verwenden. Das ist nervig und macht den code recht unübersichtlich. Kann ich also irgendwie nen Template als rückgabewert machen ohne übergabewert?

Patrick

Alter Hase

Beiträge: 1 264

Wohnort: Düren

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

2

13.10.2004, 20:41

Hi,

meinste sowas?

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
        // Gibt einen bestimmten Manager wieder

    template <typename T> inline T * getManager(void) 
    { 
            // Temporäres Objekt des angeforderten Managers

        T manager_;

            // Durchlaufe alle Manager und gib den richtigen wieder.

        for (std::vector<manager*>::iterator i=m_managers.begin(); i!=m_managers.end(); ++i) 
        {
                // Manager stimmt mit dem angeforderten Manager überein?

            if ((*i)->getID() == manager_.getID()) 
                return (static_cast<T *>(*i)); 
        }
        
            // Manager ist nicht vorhanden! Wir geben NULL zurück

        return (NULL); 
    } 

// wird so aufgerufen:


blub.getManager<keyboard>()->setKey('A');


Oder was meinst du mit Übergabewert, ich denk mal parameter, gell? :D

PD

unregistriert

3

13.10.2004, 21:55

jaja, parameter ^^

Jo, sowas meinte ich :) Und dem namen der klasse zu urteilen dient das Beispiel dem selben zweck wie ichs brauch *g* Danke vielmals :)

[Edit]
Wodurch genau erkennt der jetzt eigentlich was fürn typ T eigentlich ist? ^^

Patrick

Alter Hase

Beiträge: 1 264

Wohnort: Düren

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

4

13.10.2004, 22:06

das wird mit eincompiliert, der typ ist das was in den <> steht. :)

PD

unregistriert

5

13.10.2004, 22:12

Ok, Aufruf:

C-/C++-Quelltext

1
cObjm.GetObj<CGrafik>("CGrafik")->update();


Methode:

C-/C++-Quelltext

1
2
3
4
5
template <typename T> T *CObjectManager::GetObj(std::string com) {

    return static_cast<T*>(vpObject[GetIDbyComment(com)]);

}


GetIDbyObject sucht die ID eines objects und vpObject issn Array aus void pointern die auf besagte Objekte zeigen.

Fehler:

Quellcode

1
C:\Dokumente und Einstellungen\PQ\Desktop\Programmieren\The Labyrinth\mainclass.cpp(52) : error C2275: "CGrafik" : Ungültige Verwendung dieses Typs als  Ausdruck

Patrick

Alter Hase

Beiträge: 1 264

Wohnort: Düren

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

6

13.10.2004, 22:20

Ähme ohne auf den Fehler genauer ein zu gehen, ich würd nicht den Klassennamen auch als Parameter angeben (stellt sich nun die frage, nimmt der den parameter als klassennamen oder den typename? :D)

Ich habs so gemacht: alles vom interface manager abgeleitet und dann in den vector eines management-managers gestopft, dabei hat jeder manager eine eigene type_id (unsigned int) welche dann so abgefragt werden kann wie in meinem code (kurz: ohne parameter!).

Wenn du willst kann ich ja mal was von posten :)

PD

unregistriert

7

13.10.2004, 22:27

Ich habs so (nur mal zur erläuterung):

Eine Klasse CObjectManager welche beliebig viele Objekte verwalten kann. Jedes Objekt hat ne ID (Array Index) und nen namen als string damit ich net mit den IDs rumhantieren muss ^^
Mit AddObject() füge ich die Adresse eines Objekts hinzu und kann gleichzeitig nen Kommentar oder Namen angeben welcher eben zur Klartext identifikation dient (in dem fall "CGrafik", könnte aber genausogut "Handwurst" heißen *fg*). Und über GetObj() wahlweise per ID oder String (Kommentar/Name) bekomme ich eben die Adresse des gespeicherten Objekts. Das is halt damit jede Funktion/Klasse welche den Manager kennt auf alle Objekte zugreifen kann. (hatte ich ja mal in nem andren thread erläutert :))

Und das funktioniert ja alles sehr gut bis auf das nervige casten ;) Und weil ich keinen blassen schimmer hab was genau du mir grade verkaufen wolltest *ggg* kannste gerne mal was davon posten ^^ Aber wäre trotzdem schön wenn du versuchen könntest den fehler zu finden weil mich das jetzt intressiert :P

Patrick

Alter Hase

Beiträge: 1 264

Wohnort: Düren

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

8

13.10.2004, 22:37

Hi,

so gehts bei mir:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class manager 
{ 
public: 
        // Con- und Destructor

    manager                     (void) : m_id (0xFF000000)  {}; 
    virtual ~manager            (void)                      {}; 

        // Funktion gibt die ID des Managers wieder

    inline virtual int getID    (void) { return (m_id); } 

        // Hauptfunktionen der Manager

    virtual void restore        (void) = 0;
    virtual void clear          (void) = 0;
    virtual void update         (void) = 0;

protected:
        // ID des Managers

    int m_id; 
}; 


keyboardmanager

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
class keyboard : public manager
{ 
public: 
        // Con- und Destructor

    keyboard            (void); 
    ~keyboard           (void); 

        // Funktion gibt die ID des Managers wieder

    inline virtual int getID    (void) { return (m_id); } 

        // ### Hauptfunktionen der Manager

    void restore        (void);
    void clear          (void);
    void update         (void);

        // ### Nebenfunktionen dieses Managers 


        // Setze die gedrückten und losgelassenen Tasten

    void setPressedKey  (unsigned int key);
    void setReleasedKey (unsigned int key);

        // Welche Taste wurde/wird gedrückt?

    bool isPressed      (unsigned int key);
    bool isReleased     (unsigned int key);

protected:
        // ID des Managers

    int     m_id; 

        // Speicherung der Tasten

    bool    m_currKey[256];
    bool    m_oldKey[256];
}; 



keyboard::keyboard (void) : m_id (0xFF000001)
{
        // Alles auf 'false' setzen

    restore ();
}

keyboard::~keyboard (void)
{
}

void keyboard::restore (void)
{
        // Durchlaufe alle Einträge und setze sie auf 'false'.

    for (int i=0; i<256; ++i)
    {
        m_oldKey[i] = m_currKey[i] = false;
    }
}

void keyboard::update (void)
{
        // Aus neu mach alt für den nächsten Frame. :-D

    for (int i=0; i<256; ++i)
    {
        m_oldKey[i] = m_currKey[i];
    }
}

void keyboard::clear (void)
{
    restore ();
}


und nun das management für alle manager:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
class management : public manager 
{ 
public: 
        // Con- und Destructor

    management  (void);
    ~management (void);

        // Funktion gibt die ID des Managers wieder

    inline virtual int getID    (void) { return (m_id); } 

        // ### Hauptfunktionen der Manager

    void restore    (void);
    void clear      (void);
    void update     (void);

        // ### Nebenfunktionen dieses Managers 


        // Fügt einen Manager hinzu

    bool addManager(manager & manager_);

        // Gibt einen bestimmten Manager wieder

    template <typename T> inline T * getManager(void) 
    { 
            // Temporäres Objekt des angeforderten Managers

        T manager_;

            // Durchlaufe alle Manager und gib den richtigen wieder.

        for (std::vector<manager*>::iterator i=m_managers.begin(); i!=m_managers.end(); ++i) 
        {
                // Manager stimmt mit dem angeforderten Manager überein?

            if ((*i)->getID() == manager_.getID()) 
                return (static_cast<T *>(*i)); 
        }
        
            // Manager ist nicht vorhanden! Wir geben NULL zurück

        return (NULL); 
    } 

protected:
        // ID des Managers

    int     m_id; 
private: 
    std::vector <manager*> m_managers; 
}; 


management::management (void) : m_id (0xFFFFFFFF)
{
}

management::~management (void)
{
}

void management::restore (void)
{
        // Durchlaufe alle Einträge und setze rufe die 'restore'-Funktion auf.

    for (std::vector<manager*>::iterator i=m_managers.begin(); i!=m_managers.end(); ++i) 
    {
        (*i)->restore ();
    }
}

void management::clear (void)
{
        // Durchlaufe alle Einträge und setze rufe die 'restore'-Funktion auf.

    for (std::vector<manager*>::iterator i=m_managers.begin(); i!=m_managers.end(); ++i) 
    {
        (*i)->clear ();
    }
}


void management::update (void)
{
        // Durchlaufe alle Einträge und setze rufe die 'restore'-Funktion auf.

    for (std::vector<manager*>::iterator i=m_managers.begin(); i!=m_managers.end(); ++i) 
    {
        (*i)->update ();
    }
}

bool management::addManager(manager & manager_) 
{ 
    PUSH;

        // Guck nach ob Manager schon im Management vorhanden ist

    for (std::vector<manager*>::iterator i=m_managers.begin(); i!=m_managers.end(); ++i) 
    {
            // Existiert Manager schon?

        if ((*i)->getID() == manager_.getID()) 
        {
                // Warnung ins Log schreiben und Funktion beenden

            LOG << fm ("Der Manager ist bereits im Management enthalten!", WARNING);

            POP;

            return (false);
        }
    }

        // Manager ist noch nicht vorhanden, also rein damit und Funktion beenden

    m_managers.push_back(&manager_); 

    POP;

    return (true);
} 


Funzt perfekt :)

Achja, mal so ne rein formelle frage:

Wenn du einen Manager mit <CGraphic> haben willst auch noch den Klassennamen als Parameter übergibst, glaubst du nicht das das mit dem Parameter unnütz ist? Also eine einfache get-Methode in jedem Manager reicht doch sowie eine einzigartige ID ;)

Ansonsten finde ich das konzept mit dem Parameter relativ vorbei geschossen :D

- Patrick

PD

unregistriert

9

13.10.2004, 22:43

Na, die sache ist ja die das ich nur einen manager hab in dem beliebig viele Objekte von jeder beliebigen klasse speichern kann ^^ Und da ich net wüsste wie ich unter den.. KA... 5 void pointern blos durch das <CGrafik> des templates den richtigen rauskriegen soll hab ich eben den übergabe parameter um den richtigen rauszusuchen ^^

Aber ich werd mir mal (morgen) dein system ansehen und versuchen es zu verstehen *g*

btw: Wieso gibst du der m_id nen Hex Wert? ^^ Ich versuch mich grad nochma was tiefer in die Programmierung zu stürzen (bei mir war bisher alles etwas oberflächlich) ;)

Patrick

Alter Hase

Beiträge: 1 264

Wohnort: Düren

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

10

13.10.2004, 22:53

fand hex einfach schöner :D war zu faul extra dafür ne 64bit zufallszahl zu generieren und in einen __int64 reinzustopfen :D

Werbeanzeige