Objekte werden zerstört

BLR

Erfahrenes Mitglied
Hallo zusammen,
ich habe mit c++ angefangen und habe dabei folgendes Proble:

In der main hab ich nen Vector vom Typ "Auto"
Code:
  vector<Auto> Lvz;
    
    populate(Lvz);

Und in einer Supportfunktion, sprich einer Funktion, die an keiner Klasse hängt fülle ich den:
Code:
void populate(vector<Liwanze> &li) {


    li.push_back(Auto("Joey", Auto::amer));
    li.push_back(Auto("Johnny", Auto::amer));
    li.push_back(Auto("DeeDee", Auto::amer));
    li.push_back(Auto("Suzy", Auto::apac));
    li.push_back(Auto("Sheena", Auto::amer));
    
}

nun möchte ich diese Funktion diesen gefüllten Vector in der main ausgeben.
Problem dabei ist, dass er direkt in den Destruktor reingeht, sodass am Ende mein Vector in der main leer ist.

Meine Absicht ist also mehrere Objekte in einer klassenlosen Funktion erzeugen und diese in der Main ausgeben.
Wie kriege ich das hin?
Danke für jeden Tipp
 
Hallo BLR,

welcher Destruktor wird aufgerufen und wie hast du das überprüft? Kannst du ein vollständiges Beispiel (inkl. main) einstellen?

Grüße
Matthias
 
geprüft habe ich das, in dem ich gedebugt habe :)
der wird aufgerufen:

Code:
Auto::~Auto() {
}

Code:
int main(int argc, char** argv) {

    vector<Auto> auto;
}

Code:
#include "Auto.h"
#include <iostream>

using std::string;

//Konstruktur der aufgerufen wird

Auto::Auto(string myName, Auto marke) {

    name = myName;
    loc = myLoc;
}

dann kommt die klassenlose methode, die von der main aus aufgerufen wird
Code:
void populate(vector<Liwanze> &li) {


    li.push_back(Auto("meinAuto", Auto::golf));
   li.push_back(Auto("deinAuto", Auto::astra));
  li.push_back(Auto("seinAuto", Auto::mercedes));
  li.push_back(Auto("ihrAuto", Auto::opel));
  
   
}

Ich übergebe hier eine Referenz, also erwarte ich, dass die Veränderung am Vector auch in der main vom Vector zu erwarten ist.
Das heisst, wenn ich die Klassenlose Methode aufrufe:

Code:
populate(Lvz);

Dann ist der Vector "Lvz" nicht mehr leer.

Allerdings habe ich dann folgende Ausgabe:

Vectorgröße: 4
Name: Marke: golf
Name: Marke: golf
Name: Marke: golf
Name: Marke: golf

Danke für jeden tipp
 
Hallo BLR

Ich sehe mehrere Probleme mit deinem Code (möglicherweise auch einfach, weil er nicht vollständig ist):
1.
void populate(vector<Liwanze> &li)

Vorhin wars doch Auto?

2.
C++:
Auto::Auto(string myName, Auto marke) {
 
    name = myName;
    loc = myLoc;
}

marke wird nicht verwendet und somit auch der Member vermutlich nicht mit einem Wert belegt. Was ist myLoc?

Grüsse
Cromon
 
ja entschuldigung, es handelt sich um eine andere Klasse, aber einfachheitshalber spreche ich hier von der Klasse "Auto"

Typ vom vector ist natürlilch "Auto"

Code:
void populate(vector<Auto> &li)

und der Konstruktor vom Auto muss natürlich richtigeweise so heißen:
Code:
Auto::Auto(string myName, Auto marke) {
 
    name = myName;
    loc = marke;
}

Wie gesagt, möchte ich einfach aus der "main" heraus in einer klassenlosen Funktion paar objekte erzeugen.
Den gefühlten vector dann in der main ausgeben, also die die erzeugten Objekte in der main ausgeben wie:
Code:
cout << autoVector.at(3).getName() << autoVector.at(3).getTyp()
 
Hallo BLR,

anhand deines Codes kann ich den Fehler nicht nachvollziehen. Bitte poste doch ein vollständiges Minimalbeispiel, das man auch tatsächlich kompilieren kann. Bisher hast du nur Stückwerk geliefert und den Rest in Prosa (vermutlich verbirgt sich der Fehler im Prosa-Text).

Dass der Destruktor deiner Klasse auch vor Ende des Programms schon aufgerufen wird, ist normal. Du legst in der Funktion populate temporäre Objekte an, die dann an push_back übergeben und dort in den Vektor kopiert werden. Anschließend werden die temporären Objekte wieder zerstört und dabei der Destruktor aufgerufen. (Es sei denn der Compiler optimiert das weg.)

Grüße
Matthias

P.S.: Membervariablen initialisiert man am besten mit Initialisierungslisten. :google:
 
Ja, du hast das Problem richtig erkannt, diese Objekte werden im localen Bereich einer Methode erzeugt.
Diese Methode hat aber kein normalen Vector als Parameter sondern eine Referenz. Daher hab ich gedacht, dass die Änderung ja auch in der Aufrufenden Main da sein sollte, damit ich in der main mit diesem (von der void populate(vector<Auto> &ReferenzAuto) )

Aber auf der anderen Seite geht er natürlich in den Destructor, nach dem er mit der Methode fertig ist.....

Es funktioniert so wie du oder ich es beschrieben haben.

Da habe ich mir gedacht, dass ich den Destruktor einfach aus der .h und .cpp Datei weglasse (was unschön ist) aber der Vector in der main ist dennoch leer :(

Der Code:
Code:
int main(int argc, char** argv) {
    try {
        vector<Auto> myAuto;

        populate(myAuto);

        cout << "name: " << myAuto.at(2).getName() << " Marke: " << myAuto.at(2).getMarke();
  
}

Die .h Datei von der Klasse:
Code:
using std::string;
using std::vector;

class Auto{
public:
    
    enum Marke{ ich=0, du, er, sie};
    
    Auto();
    Auto(string auto, Marke myMarke);

    string get_name() const;
    Marke get_loc() const;



private:

    string name;
    Marke loc;
}

Die .cpp Datei
Code:
#include "Auto.h"
#include <iostream>

using std::string;



Auto::Auto(string myName, Marke myLoc) {

    name = myName;
    loc = myLoc;
}

string Auto::get_name() const {
    return name;
}

Auto::Marke Auto::get_loc() const {

    return loc;
}
Auto::~Auto() {
}

seperate globale populate-Funktion, die in der Auto.h definiert
und in der Auto.cpp implementiert ist:
Code:
void populate(vector<Auto> &li) {


    li.push_back(Liwanze("Joey", Marke::ich));
    li.push_back(Liwanze("Johnny", Marke::ich));
    li.push_back(Liwanze("DeeDee", Marke::du));
    li.push_back(Liwanze("Suzy", Marke::er));
    li.push_back(Liwanze("Sheena", Marke::sie));


}
 
Hallo BLR

Es ist sehr schwer dir zu helfen, wenn du nicht deinen Code postest. Das Beispiel von dir ist an verschiedenen Stellen offenbar vom Original abgeändert worden und compiliert nicht, einige Beispiele:
C++:
int main(...) {
   try {
     code
}

Wo lässt du die schliessende Klammer und das catch?

C++:
string get_name() const;

myAuto.at(2).getName()

Hier musst du dich entscheiden
C++:
vector<Auto> &li
push_back(Liwanze("Joey", Marke::ich))

Wieder gleich, Auto vs. Liwanze

C++:
Auto::~Auto() {
}

Im Header ist aber kein Destruktor.

Poste doch einfach deinen richtigen Code, ansonsten ist das hier heiteres Rätselraten. Und warum ist das so? Weil dein geposteter Code mit Syntaxfehlern behoben die absolut richtige Ausgabe ergibt, nämlich "name: DeeDee Marke: 1".

Viele Grüsse
Cromon
 
Entschuldigung für die Schnippsel.
hhmm....interessant, ok, dann ist hier der Code an dem ich das versuche. Die Klasse heisst anders.

Code:
#include <cstdlib>
#include <iostream>
#include <vector>
#include <stdexcept>
#include "Liwanze.h"
using std::vector;
using std::cout;
using std::cin;

/*
 * 
 */
int main(int argc, char** argv) {
    try {
        vector<Liwanze> Lvz;

        populate(Lvz);

        for (int i = 0; i < Lvz.size(); i++) {
            cout << "name: " << Lvz.at(i).get_name() << " Region: " << Lvz.at(i).get_loc();

        }


        return 0;
    } catch (...) {

        cout << "Fehlerhafte Eingabe, das Programm wurde beendet\n";
    }
}

Headerdatei

Code:
#ifndef LIWANZE_H
#define	LIWANZE_H
#include <stdlib.h>
#include <iostream>
#include <vector>

using std::string;
using std::vector;

class Liwanze {
public:
    
    enum Region { ndef=0, amer, apac, emea };
    
    Liwanze(): name(""), loc(){};
    Liwanze(string myName, Region myLoc);
    string get_name() const;
    Region get_loc() const;
    void print();
    virtual ~Liwanze();
private:

    string name;
    Region loc;
 
};

void populate(vector<Liwanze> &li);
Code:
#include "Liwanze.h"
#include <iostream>

using std::string;

Liwanze::Liwanze() {
}

Liwanze::Liwanze(string myName, Region myLoc) {

    name = myName;
    loc = myLoc;
}

string Liwanze::get_name() const {
    return name;
}

Liwanze::Region Liwanze::get_loc() const {

    return loc;
}

void populate(vector<Liwanze> &li) {


    li.push_back(Liwanze("Sui", Liwanze::amer));
    li.push_back(Liwanze("Mark", Liwanze::amer));
    li.push_back(Liwanze("Robert", Liwanze::amer));
    li.push_back(Liwanze("Ralph", Liwanze::apac));
    li.push_back(Liwanze("Sven", Liwanze::amer));

}


So ich hoffe, dass du jetzt das Problem nachstellen kannst :)
Danke dir im Voraus
 
Hallo BLR

Nachdem ich die Syntaxfehler behoben habe funktioniert auch dieser Code einwandfrei. Das folgende ist nicht gut:
C++:
Liwanze(): name(""), loc(){};

Liwanze::Liwanze() {
}

Wenn du den Konstruktor im Header mit einem Funktionskörper versiehst darfst du das nicht in der cpp auch nochmals machen.

C++:
virtual ~Liwanze();

Wird nirgendwo implementiert -> Linkerfehler

Liwanze.h fehlt das #endif, ist wohl nicht mitkopiert.

C++:
cout << "name: " << Lvz.at(i).get_name()

Für den operator std::eek:stream << std::string musst du den Header <string> includieren.

Viele Grüsse
Cromon
 

Neue Beiträge

Zurück