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

verrueckt1993

Frischling

  • »verrueckt1993« ist der Autor dieses Themas

Beiträge: 85

Beruf: Informationstechnischer Assistent Fachrichtung AE, 2. Jahr

  • Private Nachricht senden

1

31.01.2011, 12:59

[C++] Private Vererbungshierarchie

Moin moin,

ich sitze grade im Programmierunterricht und sowohl ich als auch mein Lehrer verzweifeln gerade an der privaten Vererbung.
(Bitte keine Diskussionen über den Sinn der Übung, ich fände eine gemeinsame "abstrakte" Klasse Datum auch sinnvoller, aber dazu ist dieser Fred nicht da.)

Die oberste Basisklasse Din_datum sieht folgendermaßen aus:

Din_datum.h:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
#pragma once
#include <iostream>

class Din_datum
{
public:

    void set_date(void);
    void get_date(void);

protected:
    int m_jahr, m_monat, m_tag;
};


Din_datum.cpp:

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
#include "Din_datum.h"

using std::cout;
using std::cin;
using std::endl;


void Din_datum::get_date()
{
    cout<<m_jahr<<"-"<<m_monat<<"-"<<m_jahr<<endl;
}

void Din_datum::set_date()
{
    cout<<"Jahr: ";
    cin>>m_jahr;
    cout<<"Monat: ";
    cin>>m_monat;
    cout<<"Tag: ";
    cin>>m_tag;
    cin.get();
}


Die erste Tochterklasse Am_datum erbt öffentlich von Din_datum und funktioniert wunderbar:

Am_datum.h:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
#pragma once
#include "din_datum.h"
class Am_datum : public Din_datum
{
public:

    void get_date(void);
};


Am_datum.cpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
#include "Am_datum.h"

using std::cout;
using std::endl;

void Am_datum::get_date(void)
{
    std::cout<<m_monat<<"/"<<m_tag<<"/"<<m_jahr<<std::endl;
}


Die folgende Klasse De_datum erbt privat von Am_datum:

De_datum.h:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
#pragma once
#include "am_datum.h"
class De_datum : private Am_datum
{
public:

    Din_datum::set_date;
    Din_datum::get_date;
    Am_datum::get_date;

    void get_date_new(void);
};


De_datum.cpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
#include "De_datum.h"

using std::cout;
using std::endl;


void De_datum::get_date_new(void)
{
    cout<<m_tag<<"."<<m_monat<<"."<<m_jahr<<endl;
}


Der Zugriff auf den geerbten Member get_date() von Am_Datum oder Din_datum ist nur möglich, wenn ich nur einen von beiden wieder sichtbar mache, also z.B. Din_datum::set_date; auskommentiere. Ein Zugriff über den ::-Operator funktioniert nicht. Fehlermeldung (VS 10, sieht bei Code::Blocks ähnlich aus): Die Konvertierung in die Basisklasse Am_datum, auf die nicht zugegriffen werden kann, ist nicht zulässig.

zu guter Letzt dann noch die main.cpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "De_datum.h"

using std::cin;

int main(void)
{
    De_datum* obj_de_datum = new De_datum();
    obj_de_datum->set_date();
    obj_de_datum->Am_datum::get_date();
    obj_de_datum->get_date_new();

    cin.get();
}


Vielen Dank an alle, die sich hier durch gewälzt haben und vielleicht sogar noch antworten :)

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

31.01.2011, 13:20

Da De_datum private von Am_datum erbt ist De_datum nach außen kein Am_datum. Ein Zugriff auf das Basisklassenobjekt ist nur innerhalb der Klasse De_datum möglich. Das ist auch genau was die Fehlermeldung sagt. Der Ausdruck obj_de_datum->Am_datum::get_date(); ist nicht gültig da De_datum von Außen betrachtet gar kein Am_datum ist. Wenn eine Klasse private von einer anderen Klasse erbt dann modelliert das von außen gesehen keine ist-ein Beziehung sondern eher eine hat-ein Beziehung.

C-/C++-Quelltext

1
2
3
class De_datum : private Am_datum
{
};

entspricht also von Außen betrachtet eher dem:

C-/C++-Quelltext

1
2
3
4
class De_datum
{
   Am_datum datum;
};

verrueckt1993

Frischling

  • »verrueckt1993« ist der Autor dieses Themas

Beiträge: 85

Beruf: Informationstechnischer Assistent Fachrichtung AE, 2. Jahr

  • Private Nachricht senden

3

31.01.2011, 13:22

wir sollen beide Funktionen aufrufen können. Geht das denn überhaupt irgendwie mit privater vererbung?

EDIT: macht man Hat-eine-Beziehungen nicht über Instanzen als Member der Klasse?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

31.01.2011, 13:24

wir sollen beide Funktionen aufrufen können. Geht das denn überhaupt irgendwie mit privater vererbung?

nein.

EDIT: macht man Hat-eine-Beziehungen nicht über Instanzen als Member der Klasse?

Ja normalerweise. Aber manchmal verwendet man auch private Vererbung dafür, wenn diese einem gewisse Vorteile bietet (z.B. weil man autom. alle Memberfunktionen der privaten Basis erbt).

verrueckt1993

Frischling

  • »verrueckt1993« ist der Autor dieses Themas

Beiträge: 85

Beruf: Informationstechnischer Assistent Fachrichtung AE, 2. Jahr

  • Private Nachricht senden

5

31.01.2011, 13:26

Seltsam. Mein Programmierlehrer meint, dass das eigentlich so gehen müsste. Kannst du das vllt ausführlicher begründen?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

31.01.2011, 13:30

Sagte ich doch schon. Du kannst mit using Methoden nach außen hin sichtbar machen aber du kannst nicht explizit von außen auf den AM_datum Teil von De_datum zugreifen da dieser private ist (das ist genau was man mit private Vererbung ausdrückt):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class De_datum : private Am_datum
{
public:

    using Am_datum::get_date;
    using Din_datum::set_date;

    void get_date_new(void);
};


    obj_de_datum->set_date();  // ruft Din_datum::set_date() auf
    obj_de_datum->get_date();  // ruft Am_datum::get_date() auf
    obj_de_datum->Am_datum::get_date();  // geht nicht, von außen kein Zugriff auf die Basisklasse

verrueckt1993

Frischling

  • »verrueckt1993« ist der Autor dieses Themas

Beiträge: 85

Beruf: Informationstechnischer Assistent Fachrichtung AE, 2. Jahr

  • Private Nachricht senden

7

31.01.2011, 13:53

Will heißen, man kann das mit using sichtbar machen, aber nicht explizit mit dem ::-Operator darauf zugreifen, um das Doppeldeutigkeitsproblem zu lösen? Mein Programmierlehrer ist grad etwas dickköpfig und meint, mit Visual Studio 6 und dem Borland Builder funktioniert das genau so wie in meinem Code und meint jetzt, VS10 würde das vielleicht nicht vernünftig implementieren oder so. Gibts da vllt ne vernünftige Quelle, die ihn überzeugen würde?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

31.01.2011, 14:00

Will heißen, man kann das mit using sichtbar machen, aber nicht explizit mit dem ::-Operator darauf zugreifen, um das Doppeldeutigkeitsproblem zu lösen?

Das kann man eben gerade wegen der private Vererbung nicht. In einer Methode der Klasse De_datum ginge das aber von Außen geht es eben nicht weil die Basis private ist und nicht public.

Mein Programmierlehrer ist grad etwas dickköpfig und meint, mit Visual Studio 6 und dem Borland Builder funktioniert das genau so wie in meinem Code und meint jetzt, VS10 würde das vielleicht nicht vernünftig implementieren oder so. Gibts da vllt ne vernünftige Quelle, die ihn überzeugen würde?

Visual Studio 6.0 ist älter als der C++ Standard, wenn das dort ging (was ich um ehrlich zu sein stark bezweifle, wenn dann wäre das sicher auch damals schon ein Compilerbug gewesen) dann schön und gut. VC10 verhält sich dennoch vollkommen richtig wenn es diesen Code nicht annimmt. Wenn er dazu eine Quelle braucht dann soll er einfach den momentan gültigen C++ Standard aufschlagen:

Zitat von »ISO/IEC 14882:2003(E) §11.2 Absatz 1«

If a class is declared to be a base class for another class using the private access specifier, the public and protected members of the base class are accessible as private members of the derived class.

Und wie wir alle wissen sind private Member von außen nicht zugänglich (außer in einer friend Klasse oder Funktion), auch wenn du noch so viel scoping betreibst...

Ein working draft für den nächsten C++ Standard ist hier frei verfügbar (der aktuelle ist kostenpflichtig): http://www.open-std.org/jtc1/sc22/wg21/d…/2010/n3126.pdf. Der betreffende Absatz findet sich dort auf Seite 245 ganz oben.

Dieser Beitrag wurde bereits 11 mal editiert, zuletzt von »dot« (31.01.2011, 14:17)


Werbeanzeige