Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Problem mit multidimensionalen oop und stl strukturen

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
27.05.2012, 16:52 Uhr
distorted newbie



Hallo zusammen,

obwohl absoluter Neuling aus dem PHP-Umfeld mit wenig Ahnung von Pointern und sonstigen C-spezifischen Nicklichkeiten, möchte ich mittels OOP und stl auf möglichst einfache Weise textbasierte, mehrsprachige und multidimensionale Menüstrukturen erstellen, komme aber an einem Punkt absolut nicht weiter. - den nachstehenden Quellcode (auf das nötigste reduziert) habe ich mit...

Code:
g++ -o menue_items -std=c++0x  menue_items.cpp

...fehlerfrei kompiliert:


C++:
#include <cstdlib>
#include <map>
#include <vector>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;

class menueItemVector
{
    public:
        subMenueItem();
        ~subMenueItem(){}
};

menueItemVector::menueItemVector() {}

class menueItem: public menueItemVector
{
    public:
        vector <menueItemVector *> submenue;
        vector <menueItemVector *>::iterator i;

        menueItem();
        menueItem(string type)
        {
            this->type = type;
        }
        ~menueItem(){}
        void set_title(string lang, string desc) { this->titles[lang] = desc; }
        void show_title(string lang) { printf("\n%s\n", this->titles[lang].c_str()); }
        void display_sub_items()
        {
            for ( this->i = this->submenue.begin(); this->i != this->submenue.end(); ++this->i ) {
               i:show_title("de");
            }
        }
    private:
    string type;
    string title;
    map <string, string> titles;
};

menueItem::menueItem() {}

int main(int argc, char **argv)
{
    menueItem* obj1;
    obj1 = new menueItem;
    obj1->set_title("de", "Hauptmenü");
    obj1->set_title("en", "Main Menue");
    obj1->show_title("de");

    menueItem* obj2;
    obj2 = new menueItem;
    obj2->set_title("de", "Aktionen");
    obj2->set_title("en", "Actions");
    obj2->show_title("de");

    obj1->submenue.push_back(obj2);

    obj1->display_sub_items();
}



Die Klasse menueItemVector soll lediglich dem Zweck dienen, die Klasse menueItem (die die Klasse menueItemVector erweitert) in die Lage zu versetzen, einen Container (vector) initialisieren zu können, der wiederum beliebig viele Objekte der Klasse menueItem enthalten kann. Anders als durch Vererbung habe ich es nicht mal hinbekommen, diese Möglichkeit zu schaffen.

Wenn ich das Ganze ablaufen lasse, erhalte ich folgende Ausgaben:


Code:
Hauptmenü


Erster Aufruf der member-Funktion show_title().


Code:
Aktionen


Zweiter Aufruf der gleichen Funktion für o2 (die zweite Instanz der Klasse menueItem).


Code:
Hauptmenü


Aufruf der Funktion
Code:
display_sub_items
- hier tritt das Problem zutage.

Der Variable
Code:
title
der Objektinstanz o2 wurde mit Hilfe der Funktion
Code:
set_title()
offenbar der Wert für die jeweilige Sprache korrekt zugewiesen (in diesem Fall die Zeichenkette 'Aktionen'), wie der zweite Aufruf von
Code:
show_title()
zeigt.

Danach sollte dieses Objekt dem Objektcontainer (vector) 'submenue' der Objektinstanz o1 mit...

Code:
o1->submenue.push_back(o2);

...einverleibt werden.

Wird der Wert nun aber mit...

Code:
display_sub_items()

...wieder ausgelesen, zeigt sich, dass wider Erwarten offenbar nicht das Objekt o2, sondern das Objekt o1 in dem Objektcontainer von o1 gelandet ist, denn sonst müsste die letzte Ausgabe ja 'Aktionen' und nicht 'Hauptmenü' lauten.

Leider komme ich an diesem Punkt seit Stunden nicht weiter, gehe von einem krassen Anfängerfehler aus und wäre dankbar für jeden konstruktiven Hinweis.
--
OS: Debian 6.0.5
Compiler: g++ (Debian 4.4.5-8) 4.4.5
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
27.05.2012, 17:25 Uhr
TOSHMAX



Mit der Zeile

C++:
i:show_title("de");

rufst du nicht show_title des Elementes i auf, sondern definierst ein Label namens i und rufst nur show_title der Klasse in der du dich gerade befindest auf. Deshalb wird "Hauptmenü" ausgegeben. Richtig müsste es lauten:

C++:
(*i)->show_title("de");

Allerdings kannst du dir den Pointer als Typ des Vectors sparen, da das nach obigem Code unnötig und noch dazu verwirrend ist. Mal ganz abgesehen von eventuellen Speicherlecks.

Dieser Post wurde am 27.05.2012 um 17:26 Uhr von TOSHMAX editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
29.05.2012, 11:29 Uhr
distorted newbie



Hallo TOSHMAX,

Erst mal vielen Dank für Deine Hilfestellung. Ehrlich gesagt war ich an dem Nachmittag, an dem ich das Ding gepostet habe, nervlich schon ziemlich auf Null. Was die Speicherlecks angeht, hast Du selbstverständlich recht, obwohl es mir erst mal reicht, überhaupt eine lauffähiges Struktur mit den eingangs erwähnten Funktionlitäten zustande zu bringen. Dass der Doppelpunkt an der Stelle eine Verlegensheitslösung war, war mir auch relativ klar, aber der (eigentlich logische) Pfeil führte zu einem Kompilierungsfehler.

Wie dem auch sei - ich habe den ganzen Krempel überarbeitet (zunächst mal, ohne mögliche Lecks zu berücksichtigen) und es funktioniert jetzt mit Einschränkungen, auf die ich weiter unten noch zu sprechen kommen möchte:


C++:
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <string>
#include <map>
#include <vector>

using namespace std;


class menueItemBase
{
    public:
    int var1;
    string var2;
    map <string, string> titles;

    menueItemBase();
    ~menueItemBase(){}

    void show_title(string lang) { cout << this->titles[lang].c_str() << endl; }
    void set_title(string lang, string title) { this->titles.insert(pair<string, string> (lang, title)); }

};

menueItemBase::menueItemBase(){}

class menueItem: public menueItemBase
{
    public:
    int counter;
    vector<menueItemBase*>subitems;

    menueItem();
    ~menueItem(){}

    void show_subitems(string lang, menueItem* obj)
    {
        for (unsigned i=0; i<obj->subitems.size(); i++)
        {
            obj->subitems[i]->show_title(lang);
            //obj->subitems[i]->show_subitems(lang, obj->subitems[i]);
        }
    };
};

menueItem::menueItem() {}

int main()
{
    menueItem *o1 = new menueItem;
    o1->set_title("en", "Main Menue");
    o1->set_title("de", "Hauptmenü");

    menueItem *o2 = new menueItem;
    o2->set_title("en", "Edit");
    o2->set_title("de", "Bearbeiten");

    menueItem *o3 = new menueItem;
    o3->set_title("en", "Preferences");
    o3->set_title("de", "Einstellungen");

    o2->subitems.push_back(o3);
    o1->subitems.push_back(o2);

    menueItem *o4 = new menueItem;
    o4->set_title("en", "View");
    o4->set_title("de", "Ansicht");

    cout << "--------------" << endl;

    o1->subitems.push_back(o4);

    o1->show_title("de");

    cout << "--------------" << endl;

    o1->show_subitems("de", o1);

    cout << "--------------" << endl;

    o2->show_subitems("en", o2);

    cout << "--------------" << endl;

}



Als Ausgabe liefert main() nun zunächst wunschgemäß folgendes:


Code:
--------------
Hauptmenü
--------------
Bearbeiten
Ansicht
--------------
Preferences
--------------



So wie es da steht, habe wurde dieses Gebilde fehlerfrei kompiliert es und funktioniert auch - allerdings nur (und darin besteht mein derzeitiges Problem), weil eine Zeile in der Funktion show_subitems() auskommentiert ist - dazu gleich mehr.

Zunächst einige Worte zum Aufbau:

Damit der Vektor subitems, über den jede Instanz der Klasse menueItem verfügt, Objekte aufnehmen kann, muss er benutzerdefiniert (also auf einer Klasse basieren) - soweit richtig, oder?

Der Vektor wird von der Klasse menueItemBase bereitgestellt. Neben diesem erbt die Klasse menueItem von menueItemBase ein paar Eigenschaften und Methoden (in Wirklichkeit erheblich mehr, als hier dargestellt - wie auch immer.)

Jedenfalls ist ein Objekt der Klasse menueItem nun in der Lage, in diesem Vektor beliebig viele Objekte der eigenen Art zu enthalten. Darüber war ich zunächst schon mal sehr glücklich - aber nicht allzu lange, da ich diese Objekte auch wieder rekursiv auslesen will.

Kommentiere ich in der Funktion show_subitems zu diesem Zweck die Zeile, von der ich glaubte, dass sie evtl. dafür sorgen könnte, dass die Funktion alle Vektoren aller Unterobjekte ausließt...

Code:
obj->subitems[i]->show_subitems(lang, obj->subitems[i]);

...ein, wirft der Kompiler folgenden Fehler:


Code:
menueItem.cpp: In member function ‘void menueItem::show_subitems(std::string, menueItem*)’:
menueItem.cpp:43: error: ‘class menueItemBase’ has no member named ‘show_subitems’


Das wiederum verstehe ich nicht, weil alle erzeugten Objekte als Instanzen der Klasse menuItem intialisiert wurden und diese ja doch die Funktion show_subitems() bereitstellt.

Vielen Dank im Voraus für jede weitere Hilfe und schönen Tag noch
--
OS: Debian 6.0.5
Compiler: g++ (Debian 4.4.5-8) 4.4.5
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
29.05.2012, 12:23 Uhr
distorted newbie



Kleiner Nachtrag:

Zum einen weiß ich eigentlich, wie man Compiler schreibt und dass der Dativ dem Genitiv sein Feind ist :/ aber ich stand eben etwas unter Zeitdruck.

In dem Programmlisting befindet sich noch eine überfüssige Zeile und zwar:

int counter;

Das ist nur ein Relikt von verschiedenen Tests mit rekursiven Member-Funktionen und hat weiter keine Bedeutung.
--
OS: Debian 6.0.5
Compiler: g++ (Debian 4.4.5-8) 4.4.5
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
29.05.2012, 20:57 Uhr
TOSHMAX



C++ ist typsicher, d. h. der Compiler macht keine Annahmen darüber, welches Objekt sich wo im Speicher befindet. Er weiß nur dass es ein menueItemBase ist, und das hat keine show_subitems() Methode. Du könntest jetzt zwar obj zu einem menueItem casten oder virtuelle Methoden verwenden, aber das halte ich, für den Code den ich bis jetzt kenne, für übertrieben.

Nach allem was ich bis jetzt gesehen habe, spricht aber eigentlich nichts dagegen

C++:
class menueItem
{
    public:
    vector<menueItem*>subitems;

    ...

zu schreiben und menueItemBase zu eliminieren. Damit kannst du dir einiges an Ärger mit o. g. Typ Konvertierungen sparen.
 
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: