Archiv verlassen und diese Seite im Standarddesign anzeigen : Ein paar grundlegende Fragen zu C++ (leider kein Strostrup zur Hand)
axeljaeger
11-01-2003, 13:04
1. Was habe ich davon, wenn ich eine Methode, die nicht Member einer Klasse ist, als
- static oder
- const
kennzeichne. In der Klasse bringt mir das ja was, einmal bei static das ich sie ohne ein
Exemplar der Klasse erzeugen zu müssen aufrufen kann und bei const, das die Klasse dadurch
nicht verändert wird und ich die Methode verwenden kann, auch wenn die Klasse als konstante
Referenz übergeben wird. Aber bei Nichtmemberfunktion kann ich da keine Funktion entdecken,
es ist wohl möglich und wird auch bspw. in der STL so gemacht.
2. Was bringt einem virtuelle Vererbung? Ich hab das bisher nur einmal gesehen, nämlich
im DCOP-Interface von KDE. Da steht aber nur dabei, das es eben so ist, so gemacht werden
muß und das man den Rest nicht wissen muß.
Gibt es noch änliche Spezialfälle, die in der gängigen Einsteigerliteratur nicht behandelt
werden, die man aber trotzdem kennen sollte?
3. Ich habe immer wieder gesehen, das im Konstruktor einer Klasse, wenn Parameter des
Konstruktors in Membervariablen geschrieben werden sollen, diese nicht im Body der Methode
stehen, also etwa this->parent = parent, sondern hinter einem Doppelpunkt hinter dem
Methodenkopf. Das steht auch in keinem meiner Bücher, scheint aber gängige Praxis zu sein.
4. Ich habe jetzt schon öfters Parameter von Methoden gesehen, die mit einem Unterstrich("_")
odre sogar zwei Unterstrichen ("__") vor dem Namen benannt sind. Was hat es damit auf sich?
5. Ich habe in einem Quelltext gesehen, das jmd. eine struct mit Methoden von einer class
ableitet. Was ist davon zu halten?
6. Was ist RTTI?
anda_skoa
11-01-2003, 13:24
Original geschrieben von axeljaeger
1. Was habe ich davon, wenn ich eine Methode, die nicht Member einer Klasse ist, als
- static oder
- const
zu static kann ich da nix sagen.
const geht nur bei Methoden, es macht ja auch nur dort Sinn.
Das sagt der Compiler auch, wenn du versuchst, es bei einer normalen Funktion anzugeben.
2. Was bringt einem virtuelle Vererbung? Ich hab das bisher nur einmal gesehen, nämlich
im DCOP-Interface von KDE. Da steht aber nur dabei, das es eben so ist, so gemacht werden
muß und das man den Rest nicht wissen muß.
Das braucht man, wenn man von zwei Klassen ableitet, die von der selben Basis ableiten.
Sonst ist nicht klar, aus welcher Klasse die Variablen benutzt werden sollen, die in der Basis deklariert sind.
Mit einer virtual Ableitung gibts du an, dass diese Variable eh nur einmal vorhanden ist und die mit virtuel gekennzeichnete Klasse auch auf die der anderen Klasse zugreift.
3. Ich habe immer wieder gesehen, das im Konstruktor einer Klasse, wenn Parameter des
Konstruktors in Membervariablen geschrieben werden sollen, diese nicht im Body der Methode
stehen, also etwa this->parent = parent, sondern hinter einem Doppelpunkt hinter dem
Methodenkopf. Das steht auch in keinem meiner Bücher, scheint aber gängige Praxis zu sein.
Das ist die empfohlene Methode um Instanzvariablen zu initialisieren.
Man nennt das die Initialisierungsliste.
Da wird dann für jede aufgeführte Variable der jewelige Konstruktor aufgerufen.
Auf diese Weise kann man zB als const deklarierte Instantvariablen mit einem Wert versehen.
Außerdem ist es nur ein Konstruktoraufruf, falls die Variable eine Klasse als Typ hat.
Sonst wird der Defaultkonstruktor ausgeführt und bei der Zuweisung im Body dann eine Zuweisung gemacht.
Dazu muß die Klasse aber einen Defaultkonstruktor haben und einen Zuweisungsoperator.
Über die Initialisierungsliste kann man daher auch Klassen instanzieren, die nur einen Konstruktor mit Parametern hat.
4. Ich habe jetzt schon öfters Parameter von Methoden gesehen, die mit einem Unterstrich("_")
odre sogar zwei Unterstrichen ("__") vor dem Namen benannt sind. Was hat es damit auf sich?
Wahrscheinlich eine Codekonvention im jeweiligen Source.
Ein _ ist ein normaler Namensteil.
Manchmal werden mit führenden _ Funktionen und Variablen gekennzeichnet, die Teil der internen API sind und dem Benutzer der Bibliothek nicht zur Verfügung stehen, oder von diesem nicht benutzt werden sollten.
5. Ich habe in einem Quelltext gesehen, das jmd. eine struct mit Methoden von einer class
ableitet. Was ist davon zu halten?
Kein schöner Stil, aber gültig, weil in C++ kein Unterschied zwischen struct und class ist.
D.h. ein Unterschied ist, dass bei struct alle Elemente public sind, bei class alle private, wenn nichts anderes angegeben ist.
Ich benutze eigentlich immer class.
6. Was ist RTTI?
RunTime Type Information.
Die Möglichkeit zur Laufzeit festzustellen, von welchem Typ ein Objekt ist.
Das wird zB beim dynamic_cast von der C++ Runtime benutzt, um bei inkompatiblen Typen 0 als Ergebnis zu liefern, anstatt den ungültigen Cast durchzuführen.
Ciao,
_
axeljaeger
11-01-2003, 14:14
1. Wie? Wenn ich eine Nichtmemberfunktion als const mache, für was gilt denn dann das const?
2. Ok, wahrscheinlich würde da dann zweimal von QObject geerbt
3. Kannst du nochmal ein Beispiel dazu schreiben? Den genauen Syntax hab ich leider nicht mehr im Kopf
4. Aber man muß sich nicht unbedingt dran halten. Ich finde, es dient nicht der Lesbarkeit. Ich hab mal gehört, das man daran sehen soll, was public und was private ist
5. War in libsigc, wahrscheinlich wollte der ein "public:" sparen
6. Wie soll den das gehen? Ich mache das so, das ich eine enum habe, in der alle Klassentypen drinstehen und meine basisklasse eine virtuelle Funktion hat, die dann einen Wert aus dem Enum zurückgibt. Jede erbende Klasse hat dann diese Funktion zu überschreiben. In Qt machen sie es wohl mit ihrem MOC-System, aber das ist ja auch kein Standard
anda_skoa
11-01-2003, 16:53
Original geschrieben von axeljaeger
1. Wie? Wenn ich eine Nichtmemberfunktion als const mache, für was gilt denn dann das const?
Des geht eben nicht.
Der g++ meldet bei sowas einen Fehler.
"consttest.cpp:1: non-member function `test()' cannot have `const' method qualifier"
3. Kannst du nochmal ein Beispiel dazu schreiben? Den genauen Syntax hab ich leider nicht mehr im Kopf
class B
{
public:
B(int value);
private:
int m_value;
};
B::B(int value) : m_value(value)
{
}
class A
{
public:
A(A* parent, int value);
private:
A* m_parent;
const int m_value;
B m_b;
};
A::A(A* parent, int value) : m_parent(parent), m_value(value), m_b(value)
{
}
Da m_value const int ist, kann man ihr nur so einen Wert zuweisen.
Im Body von A::A ginge das nicht mehr.
B hat keinen Defaultkonstruktor, d.h. man muß einen Parameter angeben um eine Instanz zu erzeugen.
4. Aber man muß sich nicht unbedingt dran halten. Ich finde, es dient nicht der Lesbarkeit. Ich hab mal gehört, das man daran sehen soll, was public und was private ist
das wichtige ist bei solchen Sache immer, dass sie innerhalb des selben Projektes aber zumindest innerhalb der selben Datei, konsistent sind.
6. Wie soll den das gehen? Ich mache das so, das ich eine enum habe, in der alle Klassentypen drinstehen und meine basisklasse eine virtuelle Funktion hat, die dann einen Wert aus dem Enum zurückgibt. Jede erbende Klasse hat dann diese Funktion zu überschreiben. In Qt machen sie es wohl mit ihrem MOC-System, aber das ist ja auch kein Standard
Das macht der Compiler.
Wie er das macht, weiß ich leider nicht.
Wahrscheinlich der Name der Klasse mit allen seinen Elternklassen als Präfix oder Suffix.
Oder nur die nächste Elternklasse.
Ein Enum ist für soetwas denkbar ungeeignet, weil dessen Umfang schon in der Basisklasse bekannt sein müßte.
Qt macht das, wie du schon richtig vermutet hast, mit MOC.
Das hat auch noch den Vorteil, dass du jede Klasse mit Q_OBJECT Macro nach ihrem Klassennamen fragen kannst und ob sie von einer bestimmten Klasse ableitet.
Ciao,
_
axeljaeger
11-01-2003, 18:27
1:
template <class T>
inline const T& sgn(const T& num) {
return ((num == 0) ? 0 : ((num > 0) ? 1 : -1));
}
die geht aber komischerweise. Ich teste allerdings mit dem GCC 2.96
6:
Also eigentlich versuche ich ein bißchen Qt nachzubauen.
Ich organisiere meine Objekte auch in einem Baum und so.
Da ich aber den MOC nicht verwenden will, habe ich eine enum
widgettype, die in der Basisklasse steht. Davon erbt erst sowas
wie das QObject, nur bei mir heist es anders, und dann die anderen
Widgets. Das Problem dabei ist, man kann nicht testen, ob ein Objekt
von einem anderen erbt, wenn das zu testende Objekt nicht das letzte
in der Vererbungskette steht. Ich hab z.B. einen Toolbutton, der erbt
von Pushbutton, nur können andere Objekte jetzt nicht feststellen,
ob von Pushbutton geerbt wird. Sie wissen lediglich, das es sich um
einen Toolbutton handelt. Der Gipfel ist jetzt, wenn jmd. ein eigenes
Widget schreibt, das sich als Custom ausgibt, ist vermutlich vom Rest
der Library nicht mehr benutzbar und kann von gemeinsamen Funktionen
nicht profitieren, etwa Tooltips oder auch Focushandling, weil der
Rest der Library nicht weis, das es sich eigentlich um ein Widget handelt,
das sich für den Focus interessiert oder nicht. Kann man das irgendwie besser
machen, ohne eine Art MOC zu verwenden, etwa mit Makros oder Templates?
Ich will auf jeden Fall nicht in jede Klasse manuell schreiben:
bool MToolbutton::inherits(const string& classname){
return classname == "MToolbutton" || MPushbutton::inherits(classname);
}
Schade, das es in C++ keinen typeof-Operator gibt.
hehe - Zweifel an meiner Implementation? ;-D
Warte mal noch 2 bis 3 Tage dann hast Du die neue Libversion. Damit musst Du nurnoch setClassName("...") in jedem Konstruktor aufrufen und die ganze Geschichte ist erledigt.
anda_skoa
12-01-2003, 11:22
Original geschrieben von axeljaeger
1:
template <class T>
inline const T& sgn(const T& num) {
return ((num == 0) ? 0 : ((num > 0) ? 1 : -1));
}
die geht aber komischerweise. Ich teste allerdings mit dem GCC 2.96
Die Funktion ist nicht const deklariert, also kein Problem.
6:
Also eigentlich versuche ich ein bißchen Qt nachzubauen.
Ich organisiere meine Objekte auch in einem Baum und so.
Da ich aber den MOC nicht verwenden will, habe ich eine enum
widgettype, die in der Basisklasse steht. Davon erbt erst sowas
Das halte ich für problematisch, weil das nicht erweiterbar ist.
Wäre es nicht besser, als Typ einen int oder unsigned int zu nehmen und in den jeweilinge Klassen Konstanen festzulegen?
Schade, das es in C++ keinen typeof-Operator gibt.
Wenn beim Compilieren rtti aktiviert ist (irgend eine Compilerdirektive) dann kann man e mit einem dynamic_cast machen.
Wenn das Resultat 0 ist, war der cast nicht möglich.
Ciao,
_
@anda_skoda zu 6:
Das ist eben nicht problematisch nur etwas aufwendig weil in jeder klasse so eine inherits-Methode stehen muß. Gedacht ist das so:
class XYZ : public VATERKLASSE{
public:
...
virtual bool inherits(...){
return classname=="XYZ" || VATERKLASSE::inherits(classname);
}
};
Dadurch wird bei einem inherits-Methodenaufruf die gesamte Vererbungshirarchie durchgeorgelt - also auch VATER_VON_VATERKLASSE.inherits() aufgerufen.
Nebenbei wird es in Qt so ähnlich gemacht nur das da moc die benötigten Methoden automatisch generiert.
anda_skoa
12-01-2003, 15:02
Original geschrieben von brotzi
@anda_skoda zu 6:
Das ist eben nicht problematisch nur etwas aufwendig weil in jeder klasse so eine inherits-Methode stehen muß. Gedacht ist das so:
Das hab ich schon so verstanden.
Was ich meinte war, dass es problematisch ist, wenn in der Basisklasse alle Typen in einem Enum stehen, weil das nicht erweiterbar ist.
Ciao,
_
axeljaeger
12-01-2003, 18:11
@Anda_Skoa
Wie geht denn das mit dem RTTI? Würde mich echt interessieren
@brotzi
Kann man diese Methode nicht automatisch durch ein Makro erzeugen lassen?
Powered by vBulletin® Version 4.2.5 Copyright ©2025 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.