Vector von Zeigern nach Adresse von Objekten durchsuchen



  • Hallo,
    ich habe in meiner Klasse folgenden Vektor definiert:

    class Teilnehmer {
    
    private:
    	std::string Name;
    	std::vector<Teilnehmer*> Bekannte;
    

    In Bekannte sollen die Adressen von anderen Objekten der Klasse eingetragen werden. Um zu prüfen, ob ein Teilnehmer einen anderen schon kennt habe ich folgende Methode geschrieben:

    bool Teilnehmer::kennt(const Teilnehmer& andere) const {
    	size_t pos=0;
    	pos=find(Bekannte.begin(), Bekannte.end(), &andere);
    	...
    }
    

    Allerdings meckert der Compiler rum, das beim find etwas nicht passen würde. Wo liegt mein Fehler?

    Viele Grüße


  • Administrator

    1. Wieso zeigst du uns die Fehlermeldung nicht?
    2. Rückgabewert von find ist nicht ein size_t sondern einen Iterator.
    http://www.cplusplus.com/reference/algorithm/find/
    3. Gleichheit von Objekten über deren Adresse zu prüfen, ist meistens eine schlechte Idee.

    Grüssli



  • Dann poste bitte auch WAS der Compiler zu meckern hat. Wie Eltern die meckern hat der Compiler nämlich auch was zu sagen und nicht nur zu schimpfen...

    http://www.cplusplus.com/reference/algorithm/find/
    Kennst du schon.
    Du weißt was std::vector::begin() und std::vector::end() zurückliefern?
    Dann weißt du auch dass es kein size_t ist, sondern ein std::vector::(const_)iterator.



  • Ok hier der Fehler:

    error: cannot convert '__gnu_cxx::__normal_iterator<Teilnehmer* const*, std::vector<Teilnehmer*, std::allocator<Teilnehmer*> > >' to 'size_t' in assignment
    

    also realisieren möchte ich folgendes. Die Klasse Teilnehmer stellt Personen dar. Ich möchte eine Methode bauen, das sich Teilnehmer kennen lernen können. Da wollte ich jeweils die Adressen der Bekannten in einen Vector speichern. Aber wieso ist das eine schlechte Idee?



  • size_t pos = ~size_t(0); 
    std::vector<Teilnehmer*>::const_iterator iter = find(Bekannte.begin(), Bekannte.end(), &andere);
    if( iter != Bekannte.end() ){
        pos = size_t( iter - Bekannte.begin() );
    }
    


  • Danke das find werde ich noch einarbeiten. Hier die Klasse mit manuellem Find:

    Teilnehmer.h:

    #ifndef _TEILNEHMER_H
    #define	_TEILNEHMER_H
    
    #include<vector>
    #include<string>
    
    class Teilnehmer {
    public:
        Teilnehmer(const std::string N):Name(N){};
        bool kennt(const Teilnehmer& andere) const;
        const std::string& gibNamen() const{return Name;}
        void lerntKennen(Teilnehmer&);
        void druckeBekannte() const;
    private:
        std::string Name;
        std::vector<Teilnehmer*> Bekannte;
    
    };
    
    #endif
    

    Teilnehmer.cpp:

    #include <iostream>
    #include <algorithm>
    #include <vector>
    
    #include "Teilnehmer.h"
    
    using namespace std;
    
    bool Teilnehmer::kennt(const Teilnehmer& andere) const {
        size_t Anzahl=Bekannte.size();
        for (size_t i=0; i<Anzahl;++i) {
            if(Bekannte[i]==&andere){
                return true;
            }
        }
        return false;
    }
    
    void Teilnehmer::lerntKennen(Teilnehmer& andere) {
        if( !(kennt(andere)) && (&andere != this) ) {
            Bekannte.push_back(&andere);
            andere.lerntKennen(*this);
        }
    }
    
    void Teilnehmer::druckeBekannte() const {
        size_t Anzahl=Bekannte.size();
        for(size_t i=0; i<Anzahl; ++i) {
            cout << Bekannte[i]->gibNamen()<<endl;
        }
    }
    


  • Hier noch mal mit iterator:

    bool Teilnehmer::kennt(const Teilnehmer& andere) const {
        vector<Teilnehmer*>::const_iterator iter=find(Bekannte.begin(), Bekannte.end(), &andere);
        if(iter != Bekannte.end()) return true; else return false;
    }
    

    Zu den STL Algorithmen bin ich in meinem Buch leider noch nicht gekommen. Deshalb bin ich da ein wenig unerfahren. Dazu mal ein paar Fragen:

    Ist es nicht effizienter ohne find()? Weil wie ich es ohne gemacht habe bricht es ja sofort ab, wenn der Kandidat gefunden wurde. find() geht aber immer bis zum Schluss.

    Dann kann mir bitte jemand folgendes erklären:

    vector<Teilnehmer*>::const_iterator
    

    was bedeutet da das ::const_iterator. Das hat ja was mit Namensbereichen zu tun. Heißt das const_iterator ist aus dem Namensraum vector...?

    Danke



  • Der Anfänger! schrieb:

    find() geht aber immer bis zum Schluss.

    Woher weisst du das?

    Der Anfänger! schrieb:

    Dann kann mir bitte jemand folgendes erklären:

    vector<Teilnehmer*>::const_iterator
    

    was bedeutet da das ::const_iterator. Das hat ja was mit Namensbereichen zu tun. Heißt das const_iterator ist aus dem Namensraum vector...?

    Nein, vector<Teilnehmer*> ist eine Klasse (genauer gesagt die Instanziierung eines Klassentemplates). const_iterator ist ein Typ, der innerhalb der Klasse definiert wurde, also entweder ein typedef oder gleich eine vollständige Klassendefinition. Im Gegensatz zum iterator darf der const_iterator die referenzierten Elemente nicht verändern.

    Statt

    if(iter != Bekannte.end()) return true; else return false;
    

    kannst du übrigens Folgendes schreiben:

    return iter != Bekannte.end();
    


  • Nexus schrieb:

    Der Anfänger! schrieb:

    find() geht aber immer bis zum Schluss.

    Woher weisst du das?

    Vermutlich hat er seine eigene Implementierung der STL geschrieben ;).

    Nach der Info von hier:
    http://www.cplusplus.com/reference/algorithm/find/

    Return Value
    An iterator to the first element in the range that matches value.

    müsste man meiner Meinung nach irgendwas ziemlich falsch machen wenn man den Bereich ganz durchläuft statt nur bis zum ersten Auftreten.


  • Administrator

    Der Anfänger! schrieb:

    Ich möchte eine Methode bauen, das sich Teilnehmer kennen lernen können. Da wollte ich jeweils die Adressen der Bekannten in einen Vector speichern. Aber wieso ist das eine schlechte Idee?

    Weil du dir dadurch verbietest, einen Teilnehmer kopieren zu dürfen. Sobald du kopierst, liegt das Objekt an einer anderen Speicherstelle und die Zeiger unterscheiden sich, obwohl beide Kopien den gleichen Teilnehmer darstellen.

    Das kann auch schnell zu einer möglichen Fehlerquelle mutieren. Du wirst die Teilnehmer sicher in irgendeinem Container ablegen, sobald dieser intern die Teilnehmer rumkopiert, ist die Sache schon gelaufen.

    Entweder vergleicht man die Objekte direkt, also bietet entsprechende Vergleichsfunktionen an, oder man verwendete IDs, wie zum Beispiel in einer Datenbank. Die Gleichheit über Zeiger festzustellen kann es geben, ist aber meiner Meinung nach eher selten sinnvoll.

    Grüssli


Anmelden zum Antworten