Hallo Gemeinde,
eines gibt mit bei der Vererbung bei C++ zu grübeln (vll. ist das auch
in Sprachen so - weiß ich nicht).
Szenario:
Es gibt eine Basisklasse "Base" in der einige Methoden und
Membervariablen definiert sind.
Es gibt eine Klasse, die davon über "public" erbt - "UseMe".
In UseMe komme ich nur an "Base" Membervaiablen dran, die Public sind.
Wiso ist das nicht so, dass "UseMe" in Kopie alles von "Base" übernimmt.
Also die in "Base" als private deklarierten Member als eigene private
Member hat.
Was mich daran stört ist, wenn ich die Member in "Base" public mache,
kann ich die auch außerhalb von "UseMe" sehen.
Wiso ist es auf diese Art gelöst?
In der objektorientierten Programmierung ist es ein weit verbreitetes
Pattern, so wenig wie möglich zu exponieren.
Der Nutzen wird besonders offensichtlich, wenn die Basisklasse von
jemand anderem Entwickelt wurde, als die Kind Klasse.
Wenn der Lieferant der Bassisklasse etwas verändern möchte, muss er
lediglich darauf achten, dass die exponierten Sachen (public und
protected) kompatibel bleiben. Alle anderen Teile sind quasi
Betriebsgeheimnis und können verändert werden, ohne dass es den Benutzer
der Basisklasse tangiert.
Als praktisches Beispiel schau Dir mal Windows an. Die allermeisten
Programme, die für Windows 95 entwicklet wurden, laufen auch auf allen
neueren Windows Versionen. Das geht nur deswegen, weil Microsoft den
Größten Teil des Betriebsystems als private behandelt und nur wenige
ausgewählte Felder und Methoden exponiert.
Wenn hingegen alles public wäre, dann würden die meisten Windows
Programme nur mit der Windows Version funktionieren, mit der sie
entwickelt wurden.
Oliver S. (oliverso) schrieb:
Maude schrieb:
>> Wiso ist es auf diese Art gelöst?> Ist es nicht.> http://de.wikibooks.org/wiki/C%2B%2B-Programmierung:_Klassen#Zugriffskontrolle
aus dem Link
class EineKlasse
{
public:
int liesGeheimnis() const;
protected:
void bestimmeGeheimnis(int Wert);
private:
int geheimnis;
friend class AndereKlasse;
};
Was ist denn das???
int liesGeheimnis() const;
---------
Ein nachgeschobenes Constant für was???
Mal wieder ein C++ Geheimnis das nur eingeweihte verstehen?
Dr. Sommer (Gast) schrieb:
> Soll das ein Witz sein? Das steht in jedem C++ Buch. Man muss die> Sprache schon kennen die man verwendet.
Nein, das ist kein Witz. Ich bin nun mal mehr im C zuhause und dort gibt
es eine Funktion, einen Funktionsparameter und einen
Funktionsrückgabewert.
Wozu braucht man denn solche schrägen Konstruktionen überhaupt? Dein
Link zeigt doch auf was das nach sich zieht
" What is the meaning of const in declarations like these? The const
confuses me. "
Aha!
" When you add the const keyword to a method the this pointer will
become const, and you can therefore not change any member code. (Unless
you use mutable, more on that later).
The const keyword is part of the functions signature which means that
you can implement two similar methods, one which is called when the
object is const, and one that isn't. "
Na "toll", "gut" das es das gibt. Räusper!
Ohne wäre die Welt wahrscheinlich untergegangen.
Hauptsache so verwirrend und kompliziert wie möglich. Einfach wäre ja zu
viel verlangt.
Mork vom Ork schrieb:> Ich bin nun mal mehr im C zuhause und dort gibt> es eine Funktion, einen Funktionsparameter und einen> Funktionsrückgabewert.
Ja. Aber Paramter können auch da "const" sein. Da das "this" in C++ kein
expliziter Parameter ist, wird das eben durch das nachgestellte "const"
auf konstant gesetzt. Wenn du kein C++ kannst, solltest du dich mit "Mal
wieder ein C++ Geheimnis das nur eingeweihte verstehen?" zurückhalten
und einfach nett fragen. Oder googlen.
Mork vom Ork schrieb:> Ohne wäre die Welt wahrscheinlich untergegangen.
Ja, ohne könnte man keine const-Korrektheit umsetzen.
Mork vom Ork schrieb:> Hauptsache so verwirrend und kompliziert wie möglich. Einfach wäre ja zu> viel verlangt.
Was ist denn daran kompliziert? Wie hättest du es denn gemacht, lieber
"c" statt "const" weil kürzer und einfacher?
Dr. Sommer (Gast) schrieb:
> Da das "this" in C++ kein> expliziter Parameter ist, wird das eben durch das nachgestellte "const"> auf konstant gesetzt.
Das genau ist (mal wieder) das Problem dieser Sprache. Es gibt irgendwo
im unsichtbaren Cpp-Dickicht einen impliziten, getarnten this Parameter
und nun taucht plötzlich völlig unerwartet ein explizites Schlüsselwort
"const" an einer Stelle auf, die einem nicht sofort einleuchtet (eben
weil sie sich auf etwas unsichtbares bezieht) und entfaltet dort eine
Bedeutung, die gleichzeitig wieder durch ein anderes Schlüsselwort
(mutable) zunichte gemacht werden kann.
Na toll!
Mir ist schon klar, dass du das alles locker aus der Hosentasche
erklären kannst. Aus leidiger Erfahrung hierzu ein Satz
Diskutiere niemals mit einem C++ Kenner, denn er zieht dich auf sein
Niveau herunter, schlägt dich (locker) mit seiner Erfahrung und lässt
dich dabei blöd aussehen.
> Wie hättest du es denn gemacht
Wie haben es andere Sprachen denn gemacht, die ohne sowas auskommen? Die
müssen ja furchtbare Defizite haben.
Übrigens Danke für deine Antwort (ernst gemeint)! Denn nicht, dass du
mich falsch verstehst. Aber ich stelle mir nur allzu gerne die Sinnfrage
bei solchen Spezialitäten. Mir kommt sowas wie hier immer vor als wenn
mir das liebe Marketing allen möglichen überflüssigen Schnickschnack,
der mal für Sonderfälle erdacht wurde, nun für allgemein unverzichtbar
anpreisen will und mir dann erklärt, wie rückwärtsgewandt und blöde ich
sei, weil ich nicht gewillt bin das auf Anhieb einzusehen.
Ich hatte bloß spontan (mal wieder) das Gefühl wie öfter beispielsweise
bei LTSpice, spontan einem Bunch von undurchschaubaren Parametern
gegenüber zu stehen, die nur Helmut aufdröseln kann, weil F1 mich da zum
Such-Affen werden lässt. Natürlich hätte ich hier gockeln oder in die
C++ Schwarte schauen können und gewiss, die könnten mir so ziemlich
jedes Konstrukt dort als Weltneuheit - wie ein Dyson-Vertreter seine
1.000.000 Upm LuftZwirbelDrüse - schlau und bedeutungsvoll beschreiben
und mich dabei alt aussehen lassen.
C++ ist aber gerade nur beiläufig mein Thema. Du siehst, grundsätzlich
interessiert bin ich durchaus (allerdings eher in der Breite und nicht
nur auf C++ und das macht die Lage ein wenig schwierig).
Mork vom Ork schrieb:> Das genau ist (mal wieder) das Problem dieser Sprache. Es gibt irgendwo> im unsichtbaren Cpp-Dickicht einen impliziten, getarnten this Parameter
Wenn du implizite Dinge nicht magst, solltest du ausschließlich
Assembler verwenden. Den impliziten this-Pointer gibts in allen
OOP-Sprachen, auch C++. Er vereinfacht die Programmierung und schont
Tastaturen.
Mork vom Ork schrieb:> die einem nicht sofort einleuchtet (eben> weil sie sich auf etwas unsichtbares bezieht)
Aber Pointer-Arithmetik und Dreifach-Pointer in C sind einleuchtend? Wie
gesagt, man muss seine Sprache schon kennen...
Mork vom Ork schrieb:> Diskutiere niemals mit einem C++ Kenner, denn er zieht dich auf sein> Niveau herunter, schlägt dich (locker) mit seiner Erfahrung und lässt> dich dabei blöd aussehen.
Oi. Für das Stammtisch-Niveau haben wir hier doch schon genug "C++
Threads".
Mork vom Ork schrieb:> Wie haben es andere Sprachen denn gemacht, die ohne sowas auskommen? Die> müssen ja furchtbare Defizite haben.
Ja, haben sie. Java hat's nicht, und daher auch keine const-Korrektheit
- erschwert die Fehlersuche.
Mork vom Ork schrieb:> Mir kommt sowas wie hier immer vor als wenn> mir das liebe Marketing allen möglichen überflüssigen Schnickschnack,
Dieser Schnickschnack hilft dabei, Fehler schon beim Compilieren und
nicht erst im 918273. Unit-Test zu finden. Viele Programmierer sehen das
als hilfreich an.
Mork vom Ork schrieb:> Natürlich hätte ich hier gockeln oder in die> C++ Schwarte schauen
Ja, das musst du. C++ ist eine der komplexesten Sprachen, die lernt man
nicht vom hingucken.
Mork vom Ork schrieb:> die könnten mir so ziemlich> jedes Konstrukt dort als Weltneuheit
Du musst es ja nicht verwenden. Viele Sprachen verzichten ja sogar auf
Typsicherheit. Aber das hat andere Probleme - als ich ein mal ein
größeres Projekt in ruby (dynamisch typisiert) umgesetzt habe und durch
100 Klassen und Dateien irgendwo einen falschen Parameter suchen musste,
sehnte ich mich zurück nach C++, das diesen Fehler sofort beim
compilieren gefunden hätte!
PS: C++ hat noch eine Menge mehr schöne Dinge als nur versteckte
this-Pointer und "const" zu bieten. Wenn du bei jedem so einen Aufstand
machst ob man das wirklich braucht und ob das zu implizit ist, kommst du
da nicht weit...
Mork vom Ork schrieb:> Das genau ist (mal wieder) das Problem dieser Sprache. Es gibt irgendwo> im unsichtbaren Cpp-Dickicht einen impliziten, getarnten this Parameter> und nun taucht plötzlich völlig unerwartet ein explizites Schlüsselwort> "const" an einer Stelle auf, die einem nicht sofort einleuchtet (eben> weil sie sich auf etwas unsichtbares bezieht) und entfaltet dort eine> Bedeutung, die gleichzeitig wieder durch ein anderes Schlüsselwort> (mutable) zunichte gemacht werden kann.
Wenn du die Sprache nicht richtig lernst, sondern einfach irgendwo ein
Beispiel rausklaubst, das du nicht verstehst, ist es kein Wunder, daß
Dinge für dich unerwartet sind. Das würde dir in jeder Sprache so gehen.
> Na toll!Bevor du die Sinnhaftigkeit bestimmter Konstrukte anzweifelst,
solltest du vielleicht erstmal wenigstens versuchen, sie zu verstehen,
statt gleich als erstes relflexartig zu schimpfen.
> Diskutiere niemals mit einem C++ Kenner, denn er zieht dich auf sein> Niveau herunter, schlägt dich (locker) mit seiner Erfahrung und lässt> dich dabei blöd aussehen.
Das ist aber schon eine arg verzerrte Wahrnehmung. Was erwartest du
denn, wenn du hier im Stil von "na toll, alles Mist, wozu dieser
Quatsch" reinplatzt? Wie man in den Wald reinruft...
>> Wie hättest du es denn gemacht>> Wie haben es andere Sprachen denn gemacht, die ohne sowas auskommen? Die> müssen ja furchtbare Defizite haben.
Warum müssen sie das? Die sind halt anders. Überraschung: Verschiedene
Programmiersprachen handhaben manche Sachen unterschiedlich. Kann es
deiner Meinung nach nur die zwei Varianten geben, daß ein Sprachfeature
entweder komplett sinnlos ist oder in allen Sprachen zwingend
erforderlich?
> Übrigens Danke für deine Antwort (ernst gemeint)! Denn nicht, dass du> mich falsch verstehst. Aber ich stelle mir nur allzu gerne die Sinnfrage> bei solchen Spezialitäten.
Dagegen ist nichts einzuwenden, aber dazu solltest du erstmal die
Hintergründe kennen. Erst danach kannst du fundiert sagen, ob es deiner
Meinung nach sinnvoll ist oder nicht. Aber nur weil ein const an einer
Stelle auftaucht, an der du es nicht erwartest, gleich mal drüber zu
schimpfen, bringt nichts.
> C++ ist aber gerade nur beiläufig mein Thema. Du siehst, grundsätzlich> interessiert bin ich durchaus (allerdings eher in der Breite und nicht> nur auf C++ und das macht die Lage ein wenig schwierig).
C++ ist eine komplizierte Sprache. Das macht es natürlich schwierig, sie
zu verstehen, wenn man sich nur beiläufig drum kümmert.
Rolf Magnus (rmagnus) schrieb:
>> Übrigens Danke für deine Antwort (ernst gemeint)! Denn nicht, dass du>> mich falsch verstehst. Aber ich stelle mir nur allzu gerne die Sinnfrage>> bei solchen Spezialitäten.> Dagegen ist nichts einzuwenden, aber dazu solltest du erstmal die> Hintergründe kennen. Erst danach kannst du fundiert sagen, ob es deiner> Meinung nach sinnvoll ist oder nicht. Aber nur weil ein const an einer> Stelle auftaucht, an der du es nicht erwartest, gleich mal drüber zu> schimpfen, bringt nichts.
und Dr. Sommer (Gast) schrieb:
> PS: C++ hat noch eine Menge mehr schöne Dinge als nur versteckte> this-Pointer und "const" zu bieten. Wenn du bei jedem so einen Aufstand> machst ob man das wirklich braucht und ob das zu implizit ist, kommst du> da nicht weit...
Ja, ich weiß, dass es da einiges zu beachten gibt. Ich hab deine
Postings zu C++ hier immer mal wieder mitgelesen und wie Rolf Magnus
schrieb sind da eben die "Hintergründe" der Sprache beachtenswert. Das
const an dieser Stelle hatte halt gerade mein Verständnis etwas
strapaziert. Ich war auch gerade nicht in der "akuten Lernphase C++",
sondern sah das mit dem "const" hier im Code beiläufig. Sonst hätte ich
gewiss nicht gemeckert, sondern mich erstmal selber schlau gelesen. Aber
auch solche kleinen emotionalen Einwürfe führen manchmal wie gesagt
beiläufig zu unerwarteten Erkenntnissen, vielleicht nicht nur für mich,
sondern auch andere sind dadurch vielleicht gerade neugierig geworden.
Hab darum gestern nochmals den Gockel strapaziert und ein Beispiel
gefunden
"Konstante Memberfunktionen"
http://msdn.microsoft.com/en-us/library/6ke686zh.aspx
Das Beispiel mal eben im VS2008 Express C++ als Win32 Konsolenanwendung
compiliert. Prompt wirft der Compiler auch einen schönen Fehler an der
Stelle, wo man versucht einer read-only Member function einen Wert
zuzuweisen, nämlich
Wer jetzt anfängt nach diesem Linker error LNK2019 zu googeln, in der
Hoffnung, daraus den Fehler zu erkennen wird nicht fündig werden. Für
einen "error LNK2019" gibt es nämlich eine ganze Reihe unterschiedlicher
Gründe und man sucht sich förmlich einen Ast. Böse Falle!
Da hat MS mal wieder ein Beispiel geliefert, dass einem den Spass an C++
schnell verderben kann, weil man als Neuling mit so einer Fehlermeldung
nicht weiterkommt, sondern erst mal im Regen steht. Aber auch diese
Hürde lässt sich nehmen, indem man wieder den Gockel lieber mit
Stichworten aus dem Code bemüht und mit etwas Glück, sishe da
http://books.google.de/books?id=MeezQYeenDkC&pg=PA325&lpg=PA325&ots=bhHWOHbKmM&focus=viewport&dq=Date::Date%28int,int,int%29&hl=de
Na klar, hier
1
classDate
2
{
3
public:
4
Date(intmn,intdy,intyr);
5
intgetMonth()const;// A read-only function
6
voidsetMonth(intmn);// A write function; can't be const
7
private:
8
intmonth;
9
};
"fehlt doch was". ;-)
Wo sind die Membervariablen, damit
1
DateMyDate(7,4,1998);
hier überhaupt funktioniert?
Wo also ist die Initialisierung im Konstruktor?
Hat MS wohl weggelassen, was ich bei Lernbeispielen nahezu "tödlich"
finde, weil das schnell zu Frust führt und man nicht weiterkommt.
Also ran ans Werk, Bjarne Stroustrup's Beispiel folgend ergibt sich dann
folgender Code
1
classDate
2
{
3
public:
4
Date(intmn,intdy,intyr)// Konstruktor mit INTERNER Zuweisung
5
{
6
m=mn;
7
d=dy;
8
y=yr;
9
}
10
11
intgetMonth()const;// A read-only function
12
voidsetMonth(intmn);// A write function; can't be const
13
14
private:
15
intm,d,y;
16
intmonth;
17
};
18
19
intDate::getMonth()const
20
{
21
returnmonth;// Doesn't modify anything
22
}
23
voidDate::setMonth(intmn)
24
{
25
month=mn;// Modifies data member
26
}
27
28
intmain()
29
{
30
DateMyDate(7,4,1998);
31
constDateBirthDate(1,18,1953);
32
MyDate.setMonth(4);// Okay
33
BirthDate.getMonth();// Okay
34
//BirthDate.setMonth( 4 ); // C2662 Error
35
}
und voila, schon klappt's auch mit dem Linken. Im Debugger kann dann
verfolgt werden was genau passiert.
Beim Lesen von Stroustrup wird man dann auch drauf gestoßen, wie der
Memberinitialisierer auszuschauen hat, wenn das außerhalb der Klasse
erfolgen soll. Dann kommt der Bereichsoperator "::" ins Spiel
1
Date::Date(intmn,intdy,intyr)// Konstruktor
2
{
3
m=mn;
4
d=dy;
5
y=yr;
6
}
oder in der verkürzten Form
1
// alternative Schreibweise
2
Date::Date(intmn,intdy,intyr)// Konstruktor
3
:m(mn),d(dy),y(yr)// Memberinitialisierer
4
{
5
6
}
Also soweit mein Beispiel, welches zum Herumspielen einlädt. Nur aus
trockenen Definitionen heraus würde ich persönlich die "C++ Denke" nicht
verinnerlichen. Compilerfehler liefern aber meistens (leider nicht
immer) nützliche Hinweise.
Beim mehr zufälligem (Quer-) Lesen von Stroustrub in diesem Artikel
http://www.heise.de/developer/artikel/Interview-mit-C-Schoepfer-Bjarne-Stroustrup-2300861.html
bin ich gestern dann auch noch auf Rust gestoßen. Das werde ich mir mal
zu Gemüte führen. Der Aufreger übers const hat sich für mich also
gelohnt.
;-)
Achja, kleiner Hinweis noch, man darf natürlich gerne auch eine
vollständige main() Funktion mit Rückgabewert und Parameter verwenden
oder _tmain und vorkompilierte Header per #include "stdafx.h". Ebenso
darf man typische C++ Header einbinden. Braucht es hier aber nicht, da
hier nix zur Ausgabe verwendet wird. Nur der Vollständigkeit halber sei
das erwähnt. Keep it as simple as possible bzw. KISS-Prinzip!
Mork vom Ork schrieb:> Wer jetzt anfängt nach diesem Linker error LNK2019 zu googeln, in der> Hoffnung, daraus den Fehler zu erkennen wird nicht fündig werden. Für> einen "error LNK2019" gibt es nämlich eine ganze Reihe unterschiedlicher> Gründe und man sucht sich förmlich einen Ast. Böse Falle!
Das ist jetzt aber eine Fehlermeldung, wo einer, der schon mehr als ein
paar Tage C++ programmiert, wirklich nicht lange suchen muss. Da steht
ganz klar, dass
1
Date::Date(int,int,int)
nicht definiert ist. Hier fehlt also offensichtlich die Definition der
Memberfunktion Date der Klasse Date (also eines Konstruktors) mit
drei int-Argumenten.
Hättest du schon einmal eine richtig saftige, seitenlange Fehlermeldung
auf Grund einer inkorrekten Anwendungen eines Templates gesehen, würdest
du über die obige Meldung nur noch müde lächeln ;-)
Mork vom Ork schrieb:> bin ich gestern dann auch noch auf Rust gestoßen. Das werde ich mir mal> zu Gemüte führen.
Ja, Rust ist ein gutes Beispiel dafür, dass auch bei Programmiersprachen
mit C-ähnlicher Syntax noch deutliche Fortschritte zu dem Bestehenden
(C, C++, Java, C#, Objective-C usw.) möglich sind.
Das erste, was dir dort auffallen wird: Alle Variablen sind per Default
const, so wie es sinnvollerweise eigentlich auch in C++ sein sollte.
Soll eine Variable trotzdem überschrieben werden können, muss sie mit
mut deklariert werden.