tutorials.de Buch-Aktion 05/2012
Like Tree1Danke
  • 1 Beitrag von deepthroat
ERLEDIGT
NEIN
ANTWORTEN
8
ZUGRIFFE
454
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Avatar von Alex Duschek
    Alex Duschek Alex Duschek ist offline I AM AWESOME
    Registriert seit
    Apr 2004
    Ort
    Bartholomä (Baden-Württemberg)
    Beiträge
    514
    Hey, ich versuche gerade über die Klasse auf eine Methode zuzugreifen, aber anscheinend läuft das in C++ etwas anders als in Java. Ich kriegs jedenfalls nicht hin.

    speicher ist ein Vector gefüllt mit Objekten und die Methode soll einfach nur die Objekte ausgeben

    fahrzeug.cpp:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    // Array Ausgabe
    void Fahrzeug::printVectorItems() {
        std::cout << "--- Ihr Fahrzeugbestand ---" << std::endl;
        if (!speicher.size() == 0) {
            for (unsigned int i = 0; i < speicher.size(); i++) {
                std::cout << "--------------------------" << std::endl;
                std::cout << "Fahrzeug " << i << std::endl;
                std::cout << "Name:    " << speicher.at(i).fName << std::endl;
                std::cout << "Typ:     " << speicher.at(i).fType << std::endl;
                std::cout << "Gewicht: " << speicher.at(i).fWeight << std::endl;
            }
        }
    }

    Aus der main.cpp:
    Code :
    1
    2
    3
    4
    5
    6
    7
    
            break;
                // Bestehendes Fahrzeug löschen
            case 2:
                Fahrzeug::printVectorItems();
                break;
            case 3:
                break;

    So gehts nicht, er will ein Objekt haben und nicht die Klasse. Hab diverse Varianten mit "static" versucht. Nur die Methode, nur den Vector und beides aber er bringt mir meistens den Fehler "cannot declare member function `static void Fahrzeug:rintVectorItems()' to have static linkage". Bin grad echt etwas ratlos. In Java müsste ich doch nur die Methode static machen und könnte dann über die Klasse drauf zugreifen Wie ist das bei C++?
     

  2. #2
    Avatar von sheel
    sheel sheel ist offline Moderator
    tutorials.de Moderator
    Registriert seit
    Jul 2007
    Beiträge
    4.501
    Eigentlich auch so.
    Man muss halt (wie in Java) aufpassen, dass man in der static-Methode keine nonstatic-Attribute der Klasse verwendet.
    Woher kommt den speicher? Wenn er auch in der Klasse ist, muss er dann auch static sein.
    Zeig am besten mal die ganze Klasse

    PS: Das ewige std:: kann man sich mit einem
    using namespace std;
    am Dateianfang sparen.
     

  3. #3
    Avatar von Alex Duschek
    Alex Duschek Alex Duschek ist offline I AM AWESOME
    Registriert seit
    Apr 2004
    Ort
    Bartholomä (Baden-Württemberg)
    Beiträge
    514
    Fahrzeug.cpp

    Code :
    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
    
    #include "Fahrzeug.h"
    #include <iostream>
     
    // Konstruktor
    Fahrzeug::Fahrzeug(std::string fName, double fWeight, std::string fType) {
     
        Fahrzeug::setName(fName);
        Fahrzeug::setWeight(fWeight);
        Fahrzeug::setType(fType);
        std::cout << "Ein neues Fahrzeug wurde angelegt" << std::endl;
     
    }
     
    // Destruktor
    Fahrzeug::~Fahrzeug() {
    }
     
    // Speicherverwaltung
    void Fahrzeug::addFahrzeugToVector() {
        speicher.push_back(*this);
    }
    void Fahrzeug::removeFahrzeugFromVector(int fIndex) {
        speicher.erase(speicher.begin() + fIndex);
    }
     
    // Array Ausgabe
    static void Fahrzeug::printVectorItems() { <-- hier Fehlermeldung
        std::cout << "--- Ihr Fahrzeugbestand ---" << std::endl;
        if (!Fahrzeug::speicher.size() == 0) {
            for (unsigned int i = 0; i < Fahrzeug::speicher.size(); i++) {
                std::cout << "--------------------------" << std::endl;
                std::cout << "Fahrzeug " << i << std::endl;
                std::cout << "Name:    " << Fahrzeug::speicher.at(i).getName() << std::endl;
                std::cout << "Typ:     " << Fahrzeug::speicher.at(i).getType() << std::endl;
                std::cout << "Gewicht: " << Fahrzeug::speicher.at(i).getWeight() << std::endl;
            }
        }
    }
     
    // Getter und Setter Methoden
    void Fahrzeug::setName(std::string name) {
        fName = name;
    }
     
    void Fahrzeug::setWeight(double weight) {
        fWeight = weight;
    }
     
    void Fahrzeug::setType(std::string type) {
        fType = type;
    }
     
    std::string Fahrzeug::getName() {
        return fName;
    }
     
    double Fahrzeug::getWeight() {
        return fWeight;
    }
     
    std::string Fahrzeug::getType() {
        return fType;
    }

    Fahrzeug.h
    Code :
    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
    
    #include <vector>
    #include <iostream>
     
     
    /**
     * Klasse zum Erstellen eines Fahrzeugobjektes inklusive aller nötigen Methoden
     */
    class Fahrzeug {
     
    private:
        // Fahrzeugname
        std::string fName;
        // Fahrzeuggewicht
        double fWeight;
        // Fahrzeugtyp
        std::string fType;
        // Fahrzeugspeicher
        static std::vector<Fahrzeug> speicher;
    public:
        void setName(std::string);
        void setWeight(double);
        void setType(std::string);
        void addFahrzeugToVector();
        void removeFahrzeugFromVector(int);
        static void printVectorItems();
        std::string getName();
        double getWeight();
        std::string getType();
        // Konstruktor und Destruktor
        Fahrzeug(std::string, double, std::string);
        ~Fahrzeug();
     
    };

    Fehler: cannot declare member function `static void Fahrzeug:rintVectorItems()' to have static linkage

    Ich checks nicht ganz, wo da jetzt der Fehler liegt
     

  4. #4
    Avatar von sheel
    sheel sheel ist offline Moderator
    tutorials.de Moderator
    Registriert seit
    Jul 2007
    Beiträge
    4.501
    Also bei mir gehts, wenn ich Die static-Funktion im Header implementiere
     

  5. #5
    Registriert seit
    Dec 2001
    Ort
    Bayern
    Beiträge
    5.802
    Blog-Einträge
    5
    Hallo Alex,

    du musst in der Fahrzeug.cpp das static weglassen. Außerdem musst du den statischen Member speicher irgendwo definieren, am besten in der Fahrzeug.cpp:
    Code cpp:
    1
    
    std::vector<Fahrzeug> Fahrzeug::speicher;

    Desweiteren solltest du darauf achten, bei Headerdateien stets einen Include-Wächter zu verwenden.

    <edit>
    Noch ein paar Anmerkungen:

    Zitat Zitat von sheel Beitrag anzeigen
    PS: Das ewige std:: kann man sich mit einem
    using namespace std;
    am Dateianfang sparen.
    Das ist richtig, allerdings sollte man das in einer Header-Datei nie machen. Stichwort "namespace pollution".

    Zitat Zitat von Alex Duschek Beitrag anzeigen
    Code :
    1
    2
    3
    4
    
    // Speicherverwaltung
    void Fahrzeug::addFahrzeugToVector() {
        speicher.push_back(*this);
    }
    Bist du dir bewusst, dass hier wird eine Kopie deines Objektes angelegt wird? Möglicherweise ist das nicht das, was du beabsichtigst.

    Zitat Zitat von Alex Duschek Beitrag anzeigen
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    // Array Ausgabe
    static void Fahrzeug::printVectorItems() { <-- hier Fehlermeldung
        std::cout << "--- Ihr Fahrzeugbestand ---" << std::endl;
        if (!Fahrzeug::speicher.size() == 0) {
            for (unsigned int i = 0; i < Fahrzeug::speicher.size(); i++) {
                std::cout << "--------------------------" << std::endl;
                std::cout << "Fahrzeug " << i << std::endl;
                std::cout << "Name:    " << Fahrzeug::speicher.at(i).getName() << std::endl;
                std::cout << "Typ:     " << Fahrzeug::speicher.at(i).getType() << std::endl;
                std::cout << "Gewicht: " << Fahrzeug::speicher.at(i).getWeight() << std::endl;
            }
        }
    }
    Dass "!Fahrzeug::speicher.size() == 0" hier das gewünschte Ergebnis liefert, ist vermutlich nur Zufall. Der Ausdruck ist nämlich äquivalent zu "(!Fahrzeug::speicher.size()) == 0". Wahrscheinlich wolltest du aber "!(Fahrzeug::speicher.size() == 0)" haben. Du musst den Ausdruck also entweder so klammern oder besser den passenden Operator verwenden: "Fahrzeug::speicher.size() != 0". Die if-Abfrage ist aber sowieso überflüssig.

    Zur for-Schleife: Um alle Elemente eines Vektors zu durchlaufen, verwendet man (ähnlich wie in Java) in der Regel Iteratoren. Das sähe dann so aus:
    Code cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    void Fahrzeug::printVectorItems() {
        std::cout << "--- Ihr Fahrzeugbestand ---" << std::endl;
        std::vector<Fahrzeug>::iterator it = Fahrzeug::speicher.begin();
        for (int i = 0; it != Fahrzeug::speicher.end(); ++it, ++i) {
            std::cout << "--------------------------" << std::endl;
            std::cout << "Fahrzeug " << i << std::endl;
            std::cout << "Name:    " << it->getName() << std::endl;
            std::cout << "Typ:     " << it->getType() << std::endl;
            std::cout << "Gewicht: " << it->getWeight() << std::endl;
        }
    }

    Zitat Zitat von Alex Duschek Beitrag anzeigen
    Code :
    1
    2
    3
    4
    
    // Getter und Setter Methoden
    void Fahrzeug::setName(std::string name) {
        fName = name;
    }
    Aus Performance-Überlegungen wäre es hier (und in den anderen Settern sowie im Konstruktor) besser, den String als const-Referenz zu übergeben. Sonst muss der String möglicherweise zweimal umkopiert werden (einmal beim Aufruf des Setters und ein zweites mal bei der Zuweisung).
    </edit>

    Grüße,
    Matthias
    Geändert von Matthias Reitinger (23.12.09 um 01:31 Uhr)
     
    „Gib einem Menschen einen Fisch, und er wird für einen Tag satt. Lehre ihn Fischen, und er wird ein Leben lang satt.“
    “For every complex problem, there is an answer that is short, simple and wrong.”
    “Pessimism is safe, but optimism is a lot faster!”


    Aktuelles Coding Quiz: #17 - Wörter kreuz und quer

  6. #6
    Avatar von SilentWarrior
    SilentWarrior SilentWarrior ist offline Mitglied Diamant
    Registriert seit
    Dec 2001
    Beiträge
    3.078
    Hallo Matthias

    Zitat Zitat von Matthias Reitinger Beitrag anzeigen
    Code cpp:
    1
    
    for (int i = 0; it != Fahrzeug::speicher.end(); ++it, ++i)
    Gibt es einen Grund, warum du hier ++it und ++i verwendest und nicht it++ und i++, oder ist das nur persönliche Gewohnheit?
     

  7. #7
    deepthroat deepthroat ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jun 2005
    Beiträge
    8.168
    Hi.
    Zitat Zitat von SilentWarrior Beitrag anzeigen
    Gibt es einen Grund, warum du hier ++it und ++i verwendest und nicht it++ und i++, oder ist das nur persönliche Gewohnheit?
    Es ist eine gute Angewohnheit, da Präinkrementoperatoren effizienter implementiert werden können als Postinkrementoperatoren.

    Wenn man den Rückgabewert des Operators nicht benötigt, sollte man immer die Präinkrementoperatoren wählen.

    Gruß
    Geändert von deepthroat (23.12.09 um 10:12 Uhr)
    SilentWarrior bedankt sich. 
    If at first you don't succeed, try again. Then quit. No use being a damn fool about it.

  8. #8
    Avatar von sheel
    sheel sheel ist offline Moderator
    tutorials.de Moderator
    Registriert seit
    Jul 2007
    Beiträge
    4.501
    Bei i++ wird mit dem alten Wert weitergerechnet, der Wert wird erst nach der Anweisung erhöht.
    Bei ++i Wird sofort mit dem inkrementierten Wert weitergemacht.

    zb:
    Code cpp:
    1
    2
    3
    
    int i=1;
    printf("%d",i++);
    printf("%d",i);
    ergibt: 1,2

    Code cpp:
    1
    2
    3
    
    int i=1;
    printf("%d",++i);
    printf("%d",i);
    ergibt: 2,2
     

  9. #9
    Avatar von Alex Duschek
    Alex Duschek Alex Duschek ist offline I AM AWESOME
    Registriert seit
    Apr 2004
    Ort
    Bartholomä (Baden-Württemberg)
    Beiträge
    514
    Zitat Zitat von Matthias Reitinger Beitrag anzeigen
    Bist du dir bewusst, dass hier wird eine Kopie deines Objektes angelegt wird? Möglicherweise ist das nicht das, was du beabsichtigst.
    Theoretisch geht das ja schon, aber eigentlich wollte ich das aktuell erstellte Objekt in den Vector einfügen und nicht eine Kopie. Komme allerdings damit nicht so richtig klar bisher...

    Zitat Zitat von Matthias Reitinger Beitrag anzeigen
    Dass "!Fahrzeug::speicher.size() == 0" hier das gewünschte Ergebnis liefert, ist vermutlich nur Zufall. Der Ausdruck ist nämlich äquivalent zu "(!Fahrzeug::speicher.size()) == 0". Wahrscheinlich wolltest du aber "!(Fahrzeug::speicher.size() == 0)" haben. Du musst den Ausdruck also entweder so klammern oder besser den passenden Operator verwenden: "Fahrzeug::speicher.size() != 0". Die if-Abfrage ist aber sowieso überflüssig.
    Jo, Klammerfehler und überflüssige Abfrage ... verstanden ... danke

    Zitat Zitat von Matthias Reitinger Beitrag anzeigen
    Zur for-Schleife: Um alle Elemente eines Vektors zu durchlaufen, verwendet man (ähnlich wie in Java) in der Regel Iteratoren. Das sähe dann so aus:
    Code cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    void Fahrzeug::printVectorItems() {
        std::cout << "--- Ihr Fahrzeugbestand ---" << std::endl;
        std::vector<Fahrzeug>::iterator it = Fahrzeug::speicher.begin();
        for (int i = 0; it != Fahrzeug::speicher.end(); ++it, ++i) {
            std::cout << "--------------------------" << std::endl;
            std::cout << "Fahrzeug " << i << std::endl;
            std::cout << "Name:    " << it->getName() << std::endl;
            std::cout << "Typ:     " << it->getType() << std::endl;
            std::cout << "Gewicht: " << it->getWeight() << std::endl;
        }
    }
    Hmm...in Java nie benutzt, aber gut zu wissen, dass man es so machen kann, danke

    Zitat Zitat von Matthias Reitinger Beitrag anzeigen
    Aus Performance-Überlegungen wäre es hier (und in den anderen Settern sowie im Konstruktor) besser, den String als const-Referenz zu übergeben. Sonst muss der String möglicherweise zweimal umkopiert werden (einmal beim Aufruf des Setters und ein zweites mal bei der Zuweisung).
    </edit>
    Als alter Delphianer hätte ich darauf sogar selber kommen müssen

    Danke an alle für die Hilfe!
     

Ähnliche Themen

  1. settimeout in eigener klasse auf eine Methode der Klasse
    Von user2580 im Forum Javascript & Ajax
    Antworten: 2
    Letzter Beitrag: 12.04.09, 16:26
  2. Antworten: 7
    Letzter Beitrag: 11.12.07, 15:33
  3. Antworten: 2
    Letzter Beitrag: 16.01.07, 23:33
  4. Antworten: 2
    Letzter Beitrag: 06.02.06, 19:57
  5. Antworten: 2
    Letzter Beitrag: 02.08.05, 10:12