Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

06.09.2011, 11:04

virtual get-funktion bei Vererbung?

Bei folgendem Code musste ich in der classe CRaumschiff die Zeile mit der virtuellen Get-Funktion einbauen die keinen Inhalt hat, damit das Prog keinen Fehler verursacht.
Wieso muss es diese Zeile geben und wieso reicht die Get-Funktion in der Vererbung nicht aus?

C-/C++-Quelltext

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
#include <iostream>

using namespace std;

class CRaumschiff
{
protected:
    int iEnergie;

public:
    CRaumschiff()
    {
        iEnergie = 1000;
        cout << "Raumschiff erstellt" << endl;
    };
    virtual ~CRaumschiff()
    {
        cout << "Raumschiff zerstört" << endl;
    }
    virtual void Get(){};
};

class CMinenleger : public CRaumschiff
{
private:
    int iMinen;

public:
    CMinenleger(int wert)
    {
        iMinen = wert;
        cout << "Minenleger erstellt" << endl;
    }
    ~CMinenleger()
    {
        cout << "Minenleger zerstört" << endl;
    }
    void Get()
    {
        cout << "Minen: " << iMinen << endl;
        cout << "Energie: " << iEnergie << endl;
    }
};


int main()
{
    CRaumschiff *pRaumschiff = NULL;
    pRaumschiff = new CMinenleger(5);

    pRaumschiff->Get();
    
    delete pRaumschiff;
    pRaumschiff = NULL;

    getchar();

    return 0;
}
„lean over the bowl and then take a dive all of you are dead. i am alive“

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

2

06.09.2011, 11:13

Jetzt könnte man eine Instanz von CRaumschiff erstellen und CRaumschiff::Get() aufrufen. Dafür muss sie definiert sein.
Du kannst virtual void Get() = 0; schreiben um die Klasse abstrakt zu machen. Dann brauchst du Get nicht definierten, kannst aber keine Instanz von CRaumschiff mehr erstellen :D

edit: wieso Initialisierst du pRaumschiff nicht sofort?

C-/C++-Quelltext

1
CRaumschiff *pRaumschiff = new CMinenleger(5);

funktioniert doch auch.

Und nach dem delete brauchst du den Zeiger auch nicht mehr auf null setzen weil du den Gültigkeitsbereich sowieso gleich verlässt.^^

Übrigens sollte CRaumschiff iEnergie selbst ausgeben. Es würde also sinn machen Get() zu definieren und sie in der Methode von Minenleger aufzurufen^^
Noch besser wäre eine private virtuelle Methode:

C-/C++-Quelltext

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
class CRaumschiff
{
    virtual void MyGet() = 0;
protected:
    int iEnergie;

public:
    CRaumschiff()
    {
        iEnergie = 1000;
        cout << "Raumschiff erstellt" << endl;
    };
    virtual ~CRaumschiff()
    {
        cout << "Raumschiff zerstört" << endl;
    }
  void Get(){
        cout << "Energie: " << iEnergie << endl;
        MyGet();
    };
};

class CMinenleger : public CRaumschiff
{
private:
    int iMinen;

public:
    CMinenleger(int wert)
    {
        iMinen = wert;
        cout << "Minenleger erstellt" << endl;
    }
    ~CMinenleger()
    {
        cout << "Minenleger zerstört" << endl;
    }
private:
    virtual void MyGet()
    {
        cout << "Minen: " << iMinen << endl;
    }
};


so kannst du es nicht vergessen Get von CRaumschiff aufzurufen. ;)
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »NachoMan« (06.09.2011, 11:21)


3

06.09.2011, 11:13

Naja woher soll den die Klassen CRaumschiff wissen das die abgeleitete Klasse CMinenleger eine Funktion Get() hat?
Genau sie weiß es nicht, deshalb deklarierst du sie virtual und implementierst sie dann in der abgeleiteten Klasse.

Und wenn du willst das man die Funktion implementieren muss weil sie halt jedes Raumschiff benötigt, dann kannst du schreiben
virtual Get() = 0;
Und schon muss die Funktion implementiert werden, weil die Klasse sonst nicht instanziiert werden kann.

Edit:
Zu lahm :D

4

06.09.2011, 12:48

Ok, das ist verständlich.

Aber wenn mir erst einfällt, dass ich beim Minenleger oder Gleiter oder sonst einem Raumschiff eine bestimmte Funktion haben möchte, muss
ich dann jedesmall in der Raumschiff-Klasse eine virtuelle Funktion einfügen? Somit hat dann die Raumschiff-Klasse zumindest sowas wie virtuelle Prototypen
der geerbten Klassen. Hat also Minenleger 2 Funktionen, Gleiter 2 Funktionen, dann hat Raumschiff 4 virtuelle Funktionen, oder?
„lean over the bowl and then take a dive all of you are dead. i am alive“

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

5

06.09.2011, 13:06

Funktionen die speziell für Minenleger bzw. Gleiter sind, gehören nicht in Raumschiff. Denn sie sind ja speziell für Minenleger bzw. Gleiter und nicht allgemein für alle Raumschiffe...

6

06.09.2011, 13:42

Aber ich kann nur auf Funktionen innerhalb von CRaumschiff zugreifen, wenn ich das so code

C-/C++-Quelltext

1
2
CRaumschiff *pSchiffe = new CMinenleger;
pSchiffe->Get();


Bei "pSchiffe->..." bringt er mir nur Funktionen, die unter CRaumschiff aufgeführt sind.

Nur wenn ich es so code

C-/C++-Quelltext

1
2
CMinenleger *pMiner;
pMiner.Get();


kann ich auf eine virtuelle Get-Funktion unter CRaumschiff verzichten und greife direkt per Minenleger-Variable auf Memberfunktionen zu.

Wenn ich also erst eine Variable vom Typ CRaumschiff mache und dann zuweise, dass es ein neues Minenleger-Objekt sein soll, kann ich mit dieser Variablen nur auf Dinge unter CRaumschiff zugreifen, ausser ich mach diese virtuell, dann überschreibt er die Funktion unter CRaumschiff mit der aus CMinenleger aber dann hab ich sozusagen einen virtuellen Prototypen unter CRaumschiff und die Funktion selbst in den geerbten Klassen.
„lean over the bowl and then take a dive all of you are dead. i am alive“

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

7

06.09.2011, 13:47

Bei "pSchiffe->..." bringt er mir nur Funktionen, die unter CRaumschiff aufgeführt sind.

Um, ja klar, pSchiffe zeigt ja auch auf ein Raumschiff!?

Wenn ich also erst eine Variable vom Typ CRaumschiff mache und dann zuweise, dass es ein neues Minenleger-Objekt sein soll, kann ich mit dieser Variablen nur auf Dinge unter CRaumschiff zugreifen [...]

Ja klar, was denn sonst. Deine Variable zeigt ja auch ein Raumschiff und nicht auf einen Minenleger!?

8

06.09.2011, 13:57

Ich glaube ich hab mich da etwas mit den Typen der Variablen vertan.

Ich dachte man macht erst eine Variable vom Typ CRaumschiff um dann später das jeweilige spezielle Raumschiff "reinzupacken".
Aber ich glaube ich muss gleich eine variable vom speziellen Raumschifftyp erstellen und auch nur diese spezielle Art reinpacken.

Edit: Damit ihr seht was ich grad mach, hier meine 2 Codes, einmal eher falsch und einmal eher richtig :-)

C-/C++-Quelltext

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <iostream>
#include <list>
#include <conio.h>

using namespace std;

class CRaumschiff
{
protected:
    int iEnergie;

public:
    CRaumschiff()
    {
        iEnergie = 100;
        zaehler ++;
        cout << "Ein Raumschiff vom Typ";
    };

    virtual ~CRaumschiff(){}

    virtual void Get() = 0;
    virtual void Starten() = 0;

    static int zaehler;
};

class CMinenleger : public CRaumschiff
{
private:
    int iId;
    int iMinen;

public:
    CMinenleger(int minen, int id)
    {
        iId = id;
        iMinen = minen;
        cout << " Minenleger erstellt" << endl;
        cout << "Anzahl Raumschiffe: " << zaehler << endl;
    }
    ~CMinenleger()
    {
        zaehler --;
        cout << "Minenleger zerstört" << endl;
        cout << "Anzahl Raumschiffe: " << zaehler << endl;
    }

    void Get()
    {
        cout << "Anzahl Minen an Board von Minenleger Nr. " << iId << ": " << iMinen << endl;
        cout << "Energie des Minenlegers: " << iEnergie << endl;
    }
    void Starten()
    {
        cout << "Minenleger startet" << endl;
    }
};

int CRaumschiff::zaehler = 0;

int main()
{

    list<CMinenleger*> lSchiffe;
    list<CMinenleger*>::iterator i;
    int Anzahl = 0;
    int wert = 0;

    CRaumschiff *Temp = NULL;

    cout << "Wie viele Minenleger?: ";
    cin >> Anzahl;

    for(int j=0; j<Anzahl; j++)
    {
        cout << "Anzahl Minen für Minenleger Nr. " << j+1 << ": ";
        cin >> wert;
        Temp = new CMinenleger(wert, j+1);
        lSchiffe.push_back(Temp);
    }
    for(i=lSchiffe.begin(); i!=lSchiffe.end(); i++)
    {
        (*i)->Get();
        (*i)->Starten();
    }
    
    for(i=lSchiffe.begin(); i!=lSchiffe.end(); i++)
    {
        delete (*i);
        (*i) = NULL;
    }

    lSchiffe.clear();


    _getch();
    return 0;
}


C-/C++-Quelltext

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <iostream>
#include <list>
#include <conio.h>

using namespace std;

class CRaumschiff
{
protected:
    int iEnergie;

public:
    CRaumschiff()
    {
        iEnergie = 100;
        zaehler ++;
        cout << "Ein Raumschiff vom Typ";
    };

    virtual ~CRaumschiff(){}

    static int zaehler;
};

class CMinenleger : public CRaumschiff
{
private:
    int iId;
    int iMinen;

public:
    CMinenleger()
    {
        cout << " Minenleger erstellt" << endl;
        cout << "Anzahl Raumschiffe: " << zaehler << endl;
    }
    ~CMinenleger()
    {
        zaehler --;
        cout << endl << "Minenleger " << iId << " zerstört" << endl;
        cout << "Anzahl Raumschiffe: " << zaehler << endl;
    }

    void Set(int id)
    {
        iId = id;
        cout << endl << "Wie viele Minen hat Minenleger Nr. " << iId << "?: ";
        cin >> iMinen;
    }

    void Get()
    {
        cout << "Anzahl Minen an Board von Minenleger Nr. " << iId << ": " << iMinen << endl;
        cout << "Energie des Minenlegers: " << iEnergie << endl;
    }
    void Starten()
    {
        cout << "Minenleger " << iId << " startet" << endl;
    }
};

int CRaumschiff::zaehler = 0;

int main()
{
    CMinenleger *pMiner = NULL;
    int Anzahl = 0;

    cout << "Wie viele Minenleger?: ";
    cin >> Anzahl;
    cout << endl;

    pMiner = new CMinenleger[Anzahl];

    for(int j=0; j<Anzahl; j++)
    {
        pMiner[j].Set(j+1);
        pMiner[j].Get();
        pMiner[j].Starten();
    }

    delete[] pMiner;

    _getch();
    return 0;
}
„lean over the bowl and then take a dive all of you are dead. i am alive“

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »JoeChip« (06.09.2011, 14:07)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

9

06.09.2011, 14:07

Ja. Man macht eine Variable vom Typ CRaumschiff*, wenn man alle Raumschiffe gleich behandeln will, ohne wissen zu müssen, um was für eine Art Raumschiff es sich jetzt genau handelt (der * ist wichtig! Es ist eben nicht ein CRaumschiff sondern nur ein Verweis auf etwas wie ein CRaumschiff!). Jeder Minenleger ist auch ein Raumschiff. Aber nicht umgekehrt. Genau das drückt man mit Vererbung aus. Wenn du Code hast, der mit Minenlegern arbeitet, dann reicht es nicht, nur zu wissen, dass alles Raumschiffe sind, sondern dann muss dieser Code die Minenleger auch als solche kennen.

10

06.09.2011, 14:22

Wenn ich sage, dass alles Raumschiffe sind gab es Probleme beim Versuch ein Minenleger-Array zu machen und dann auf die Elemente zuzugreifen.

Mit diesem Code

C-/C++-Quelltext

1
2
3
CRaumschiff *pSchiffe = new CMinenleger[5]

pSchiffe[1].Starten();


konnte ich immer nur auf das erste Element des Arrays zugreifen.

Wenn ich es dagegen so schreibe

C-/C++-Quelltext

1
2
3
CMinenleger *pMiner = new CMinenleger[5];

pMiner[1].Starten();


geht das ohne Probleme und ich kann auf die virtuellen Funktionen in der CRaumschiff-Klasse verzichten da ich CMinenleger-Objekte habe und dieses ja auf ihre eigenen Funktionen zugreifen darf. Und trotzdem wird sowohl der Konstruktor von CRaumschiff als auch von CMinenleger aufgerufen, was eben die Vererbung zeigt.


@dot: Aus deinem letzten Post kann ich jetzt nicht ganz erkennen wie man es am besten machen soll?
Heißt es nun CRaumschiff *pSchiff = new CMinenleger oder CMinenleger *pMiner = new CMinenleger ???
„lean over the bowl and then take a dive all of you are dead. i am alive“

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »JoeChip« (06.09.2011, 14:43)


Werbeanzeige