Problem bei einer Getter Methode bei eigenem Vektor (Template)



  • Hi,

    ich hoffe es kann mir jemand auf die Sprünge helfen folgendes Problem zu lösen:

    a) im Rahmen unseres C++ Kurses habe ich mich zum Üben an einer selbstgeschriebenen Vektorklassentample, welche mit in einer internen Listendarstellung arbeitet, versucht:

    /*
     * File:   Vektor.h
     *
     * Created on 12. April 2012, 16:31
     */
    
    #ifndef VEKTOR_H
    #define    VEKTOR_H
    
    #include <iostream>
    
    template <typename T>
    class Vektor {
    public:
    
        Vektor() : size(0), pData(NULL), pNext(NULL), pLast(NULL) {
            this->pLast = this;
        };
    
        Vektor(const Vektor& orig);
    
        virtual ~Vektor() {
        };
    
        void Append(const T& object) {
            // Speicher besorgen
            Vektor<T>* newElement = new Vektor<T > ();
            // TypObject im Speicher ablegen
            newElement->pData = object;
            // Zeiger umbiegen
            this->pLast->pNext = newElement;
            this->pLast = newElement;
            // Größe erhöhen
            size++;
        }
    
        int GetSize() const {
            return this->size;
        }
    
        bool Empty(void) {
            return (this->size == 0);
        }
    
        void Print(void) {
    
            T pData = this->pData;
            Vektor<T> * pNext = this->pNext;
            Vektor<T> * act = this;
    
            std::cout << "\nNumber of Elements in Vector: " << this->size << std::endl;
    
            for (int i = 0; i < size; i++) {
                act = pNext;
                pData = pNext->pData;
                pNext = pNext->pNext;
                std::cout << "\nElement [" << i + 1 << "] on Adress: " << act;
                std::cout << "\nData:" << pData;
                std::cout << "\nNext:" << pNext << std::endl;
            }
            std::cout << std::endl;
        }
    
        const T At(int position) {
    
            if (!Empty()) {
                Vektor<T> * act = this;
                if (position < this->size) {
                    for (int i = 0; i <= position; i++) {
                        act = act->pNext;
                    }
                    return act->pData;
                }
            }
        }
    
        void Clear(void) {
            // Missing: Delete all elements from memory
            this->pNext = NULL;
            this->size = 0;
        }
    
    private:
        int size;
        T pData;
        Vektor<T>* pNext;
        Vektor<T>* pLast;
    };
    
    #endif    /* VEKTOR_H */
    

    b) nun impl. ich diesen Vektor bspw in einer weitern Klasse "Player.h" als Typ in deren private bereich und als methode:

    * File:   Player.h
     * Created on 15. April 2012, 16:41
     */
    
    #ifndef PLAYER_H
    #define	PLAYER_H
    
    #include "Vektor.h"
    #include "Piece.h"
    
    class Player {
    public:
        Player();
        Player(const Player& orig);
        void AddPiece(Piece* piece);
        virtual ~Player();
        Vektor<Piece*> GetPieces(void);
    
    private:
        Vektor<Piece*> pieces;
    };
    
    #endif	/* PLAYER_H */
    

    c) wenn ich nun allerdings die Getter-Methode benutze erhalte ich folgendern Fehler:

    /* 
     * File:   Player.cpp
     * 
     * Created on 15. April 2012, 16:41
     */
    
    #include "Player.h"
    
    Player::Player() {
    }
    
    Player::Player(const Player& orig) {
    }
    
    Player::~Player() {
    }
    
    void Player::AddPiece(Piece* piece){
        this->pieces.Append(piece);
    }
    
    Vektor<Piece*> Player::GetPieces(){
        return this->pieces;
    }
    
    Player.cpp:23: undefined reference to `Vektor<Piece*>::Vektor(Vektor<Piece*> const&)'
    

    leider kann ich den Fehler nicht richtig deuten was fehlt?!


  • Mod

    Das liegt daran, dass du in Zeile 20 deiner vektor.h einen eigenen Kopierkonstruktor deklariert hast, der aber nirgendwo definiert wird. Durch die Deklaration wird verhindert, dass der Compiler einen eigenen Kopierkonstruktor erzeugt (das tut er sonst nämlich).

    Überhaupt kommst du (oder vermutlich eher dein Lehrer) von der berüchtigten "ich habe mal Konstruktoren und Destruktoren gesehen, aber nicht verstanden"-Schule. Die ganzen leeren Konstruktoren und Destruktoren sind absolutes Alarmsignal, dass der Lehrer schlecht ist. Der leere Kopierkonstruktor in Player (und der in der Verkotrklasse, wenn du ihn ebenfalls leer implementierst) werden dir zur Laufzeit absolut grandios um die Ohren fliegen.



  • Also ich finde dein Design hat noch etwas Luft nach oben. Du hast Dir ein Problem fürs später (ja, ja ich weiß es ist nur eine Übung ) eingehandelt indem Du eine „Superklasse“ geschrieben hast. Du hast eine Listenklasse mit einer Listenknotenklasse verbinden. So etwas geht meist schief. Zumindest in den ersten n Versuchen und/oder sobald die geforderten Features etwas komplizierter werden.

    Z.B. haben deine Listenknoten überflüssige Informationen wie «size» und «pLast». Denn die sind ja nur für die Liste interessant. Variable «size» brauchst Du in deinem Design eh nicht! Deine Liste hat nur eine Richtung, also kann man solange vorwärts iterieren bis der nächste Pointer und der letzte Pointer gleich sind oder --«position» den Wert -1 trifft. Auch fällt es mir schwer das Nutzen der «GetSize()»-Methode zu sehen. Der spätere Benutzer wird mit dieser Information kaum was anfangen können ( und mir fällt gerade auf, dass dir mindestens eine return Anweisung in der «At( int )» fällt ). Insgesamt gibt es viel Vorlagen später einen Denk/Logikfehler einzubauen. Ich persönlich würde eine private «Node»-klasse schreiben.

    P.S. Der Sinn der Aufgabe verstehe ich trotzdem nicht 😞



  • Zunächsteinmal vielen lieben Dank für das Feedback.

    Was die leeren Konstruktoren/Destruktoren betrifft: Ich arbeite mit Neatbeans, wenn ich dort eine neue Klasse anlege, bekomme ich gleich standartmäßig ein paar standart destruktoren/konstruktoren von der Umgebung mit eingefügt. Diese hatte ich hier noch nicht wieder entfernt. WIe es aber aussieht, machen die in diesem Fall genau das Problem aus ^^

    Hintergrund zur Aufgabe: Wir sollen über die Zeit ein eigenes Schachprogram entwerfen. Als Vorlage haben wir einen selbstgeschrieben Vektor vom Dozent bekommen, welcher zunächst kein Template war und intern mit einer Array darstellung gearbeitet hatte.

    Als Aufgabe hiess es nun: Den Vektor
    a) zu einem Template machen und
    b) die interne Array-Darstellung gegen Liste auszutauschen.

    In diesem Vektor sollen später je nach bedarf die Figuren o. Zellen vom Schachbrett gespeichert werden.

    Ursprünglich wollte ich es auch zunächst getrennt schreiben: Mit List/Nodes getrennt, aber wir sollen es hier in "einem Ding" machen.


Anmelden zum Antworten