Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » zugriff auf attribut

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
16.09.2008, 12:59 Uhr
dafduf



huhu alle zusammen, also ich wollt mich mal mit der factory-methode beschäftigen und hab etwas nachprogrammiert, was ich in internet fand. habs nun n bissi erweitert. nun is mein problem, ich weiss nicht wie ich auf die attribute der unterklassen zugreifen kann.



C++:
#include <vector>
#include <iostream>

class Person
{
public:
    int nummer;
    static Person* erstelle_person(int auswahl);
    virtual void handlung()=0;
    virtual ~Person() {};
};

class Peter:public Person
{
public:
    std::string farbe;
    void handlung()
    {
        std::cout<<"Peter:isst ein eis"<<std::endl;
    };
};

class Pacco:public Person
{
public:
    std::string farbe;
    void handlung()
    {
        std::cout<<"Pacco:fährt auto"<<std::endl;
    };
};

class Paul:public Person
{
public:
    std::string farbe;
    void handlung()
    {
        std::cout<<"Paul:angelt ein fisch"<<std::endl;
    };
};

Person* Person::erstelle_person(int auswahl)
{
    if (auswahl==1)
    {
        return new Peter;
    }
    else
    {
        if (auswahl==2)
        {    
            return new Paul;
        }
        else
        {
            if (auswahl==3)
            {
                return new Pacco;
            };
        };
    };
    return 0;
};

void ausgabe(std::vector<Person*> personen)
{
    for (size_t i=0;i<personen.size();i++)
    {
        std::cout<<personen[i]->nummer<<"   "<<std::flush;        
        personen[i]->handlung();    
    };    
}

void nummereingabe(std::vector<Person*> personen)
{
    for (size_t i=0;i<personen.size();i++)
    {
        personen[i]->nummer=i;
    };    
};

void farbeeingabe(std::vector<Person*> personen)
{
    for (size_t i=0;i<personen.size();i++)
    {
        if (personen[i]->nummer==0)
            personen[i]->farbe='rot';
        else
            personen[i]->farbe="weiss";    
    };    
};

int main(void)
{
    std::vector<Person*> personen;
    int auswahl;
    
    while(true)
    {
        std::cout<<"1 für Peter   -   2 für Paul   -   3 für Pacco   -   alles andere zum Beenden :"<<std::endl<<"Auswahl : "<<std::flush;
        std::cin>>auswahl;
        if ((auswahl!=1) and (auswahl!=2) and (auswahl!=3))
        {
             break;
        }
        else
        {
            personen.push_back(Person::erstelle_person(auswahl));
        };
    };
    
    nummereingabe(personen);
    farbeeingabe(personen);
    ausgabe(personen);
    for (size_t i=0;i<personen.size();i++)
    {
        delete personen[i];
    };    
    std::cout<<std::endl<<std::endl<<"ENDE"<<std::endl;
    return 0;
};



in der funktion "nummerneingabe" kann ich ganz normal auf das attribut "nummer" der oberklasse zugreifen. und in funktion "farbeeingabe" möchte ich nun auf das Attribut "farbe" der Unterklasse zugreifen. aber hab da irgendwie keine ahnung , wie ich das anstellen soll, dachte vielleicht mit nem zweifache Pfeil "->->". aba das ging nicht. hoffe ihr könnt mir da helfen. vielen dank shcon mal im voraus.

grüße, dafduf
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
16.09.2008, 14:19 Uhr
ao

(Operator)


Hi,

Erstens: public-Attribute sind grundsätzlich schlecht. Gewöhn sie dir am besten sofort ab.

Zweitens: Statt "Oberklasse" und "Unterklasse" sagt man üblicherweise "Basisklasse" und "abgeleitete Klasse".

Drittens: Du hast das Factory-Pattern missverstanden. Entscheidend ist, dass die Fabrikmethode in der Basisklasse abstrakt ist und von den abgeleiteten Klassen überschrieben wird. In deinem Design steckt der Fehler, dass die Basisklasse alle von ihr abgeleiteten Klassen kennen muss, um sie erzeugen zu können (Fallunterscheidung in erstelle_person), und wenn du eine weitere Klasse (z.B. class Fritz : public Person) definierst, muss Person erweitert werden - das ist ein Widerspruch zum üblichen Ableitungs-Paradigma.

Siehe auch hier: http://de.wikipedia.org/wiki/Fabrikmethode

Zu deiner Frage: Wenn du über den Basisklassen-Zeiger auf eine Instanz zugreifst, kannst du nur Mitglieder und Methoden der Basisklasse erreichen, nicht die der abgeleiteten Klassen. Da deine abgeleiteten Klasse alle ein Member "farbe" haben - warum steckst du es nicht in die Basisklasse?

Gruß,
ao

Dieser Post wurde am 16.09.2008 um 14:20 Uhr von ao editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
17.09.2008, 07:43 Uhr
dafduf



guten morgen ao, danke ersteinmal für deine antwort.

also ich hab mich einfach auf die seite mit dem beispiel bezogen, die ich gefunden habe:

http://sourcemaking.com/design_patterns/factory_method/c++/1.

anscheinend hab ich nciht genau begriffen, worums in dieser factory-methode geht. hätte vielleicht jemand ein einfaches beispiel als quellcode, um das n bissi besser nachzuvollziehen?

zu meinem problem mit dem attribut der abgeleiteten klasse:
dies mit der "farbe" war nur ein beispiel. ziel ist es, das die abgeleiteten klassen unterschiedliche attribute haben, sonst macht es ja sowieso keinen sinn, abgeleitete klassen zu erzeugen, wenn sie alle gleich sind. wie also kann ich nun auf die attribute zugreifen. hier noch einmal die veränderte version:


C++:
#include <vector>
#include <iostream>

class Person
{
private:
    int nummer;    
public:
    void set_nummer(int m_nummer){nummer=m_nummer;};
    int get_nummer(void){return nummer;};
    static Person* erstelle_person(int auswahl);
    virtual void handlung()=0;
    virtual ~Person() {};
};

class Peter:public Person
{
private:
    std::string farbe;
public:
    void set_farbe(std::string m_farbe){farbe=m_farbe;};
    std::string get_farbe(void){return farbe;};    
    void handlung()
    {
        std::cout<<"Peter:isst ein eis"<<std::endl;
    };
};

class Paul:public Person
{
private:
    std::string farbe;
public:
    void set_farbe(std::string m_farbe){farbe=m_farbe;};
    std::string get_farbe(void){return farbe;};    
    void handlung()
    {
        std::cout<<"Paul:angelt ein fisch"<<std::endl;
    };
};

class Pacco:public Person
{
public:
    void handlung()
    {
        std::cout<<"Pacco:fährt auto"<<std::endl;
    };
};

Person* Person::erstelle_person(int auswahl)
{
    if (auswahl==1)
    {
               return new Peter;
        }
    else
    {
        if (auswahl==2)
        {    
            return new Paul;
        }
        else
        {
            if (auswahl==3)
            {
                return new Pacco;
            };
        };
    };
    return 0;
};

void ausgabe(std::vector<Person*> personen)
{
    for (size_t i=0;i<personen.size();i++)
    {
        std::cout<<personen[i]->get_nummer()<<"   "<<std::flush;
        personen[i]->handlung();    
    };    
}

void nummereingabe(std::vector<Person*> personen)
{
    for (size_t i=0;i<personen.size();i++)
    {
        personen[i]->set_nummer(i);
    };    
};

void farbeeingabe(std::vector<Person*> personen)
{
    for (size_t i=0;i<personen.size();i++)
    {
        personen[i]->farbe="rot"    ;
    };    
};

int main(void)
{
    std::vector<Person*> personen;
    int auswahl;
    
    while(true)
    {
        std::cout<<"1 für Peter   -   2 für Paul   -   3 für Pacco   -   alles andere zum Beenden :"<<std::endl<<"Auswahl : "<<std::flush;
        std::cin>>auswahl;
        if ((auswahl!=1) and (auswahl!=2) and (auswahl!=3))
        {
             break;
        }
        else
        {
            personen.push_back(Person::erstelle_person(auswahl));
        };
    };    
    nummereingabe(personen);
    farbeeingabe(personen);
    ausgabe(personen);
    for (size_t i=0;i<personen.size();i++)
    {
        delete personen[i];
    };    
    std::cout<<std::endl<<std::endl<<"ENDE"<<std::endl;
    return 0;
};



in dieser version hat nun die klasse "Pacco" das "farbe"-attribut nicht. wie kann ich nun auf das attribut "farbe" der abgeleiteten klassen "peter" und "paul" zugreifen?

vielen lieben dank für eure hilfe.

grüße, dafduf.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
17.09.2008, 08:31 Uhr
ao

(Operator)



Zitat von dafduf:
in dieser version hat nun die klasse "Pacco" das "farbe"-attribut nicht. wie kann ich nun auf das attribut "farbe" der abgeleiteten klassen "peter" und "paul" zugreifen?

Indem du für peter und paul eine weitere gemeinsame Basisklasse definierst, z.B. so:


C++:
class FarbigePerson : public Person
{
    string farbe;
    // und Getter und Setter dazu
};

class Peter : public FarbigePerson
{
};



und dann per dynamic_cast testest, ob die Instanz hinter personen[i] eine FarbigePerson ist. Falls ja, kannst du den Farbe-Getter aufrufen, falls nicht, darfst du das nicht.

Um dynamic_cast verwenden zu können, musst du am Compiler RTTI-Erweiterungen (RunTime Type Information) einschalten.

Aber auch das ist schon grenzwertig. Der Sinn einer Basisklasse ist, dass man mit allen Ableitungen das machen kann, was man mit der Basisklasse machen kann. Es ist also paradox, einen Sack voll "Person"-Instanzen zu verwalten und dann jede einzelne zu prüfen, ob sie eine "Farbe"-Methode hat oder nicht.

Wenn du jetzt nur Bahnhof verstehst: Erst mal liegenlassen und weiter Grundlagen lernen.


Zitat:
ziel ist es, das die abgeleiteten klassen unterschiedliche attribute haben, sonst macht es ja sowieso keinen sinn, abgeleitete klassen zu erzeugen, wenn sie alle gleich sind.

Eine Basisklasse führt man ein wegen der Gemeinsamkeiten, nicht wegen der Unterschiede.

Möglicherweise ist dein Beispiel etwas zu simpel, um die Auswirkungen zu sehen. Vielleicht machst du mal ein Design für geometrische Formen, z.B. Kreis, Dreieck, Rechteck. Die gemeinsame Basisklasse Figur könnte abstrakte Methoden Zeichnen(), Umfang() und Flaecheninhalt() enthalten, die von jeder Ausprägung überschrieben werden.

Diese Anwendung taugt sogar als Beispiel für das Factory-Pattern. Mit drei gegebenen Punkten sind sowohl Kreis als auch Dreieck als auch Rechteck eindeutig beschrieben, d.h. eine Fabrikmethode, die drei Punkte als Parameter nimmt, kann alle drei Figuren erzeugen.

Dieser Post wurde am 17.09.2008 um 09:03 Uhr von ao editiert.
 
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: