Deine C++ Videos sind mit Abstand die besten auf UA-cam, ich lese gerade ein C++ Buch und manchmal versteh ich halt etwas nicht... der erste Gedanke ist dann Bytes'n'Objects :D !
In der Dackel Klasse greift dann der Standartkonstruktor? Könnte ich dem Dackel auch fünf Beine geben oder geht das nicht weil er von dem Hund abgeleitet wurde und der keine Parameter annimmt...?
Dackel kann keine Konstruktorparameter nehmen, da er nur über den implizit implementierten Defaultkonstruktor verfügt. Das hat mit der Ableitung von Hund nur bedingt zu tun, sondern mit dem implizit vorhandenen Konstruktor, der vom Compiler implementiert wird, wenn sonst keiner da ist.
Eine Frage zum Vererben des Konstruktor. Warum muss ich jedes mal bei einer abgeleiteten Klasse den Konstruktor der Basis Klasse angeben. Könnte man das umgehen?
Kommt darauf an. Mit C++11 kommt Konstruktorvererbung dazu. Dann kann man mit using Base::Base die Basiskonstruktoren einfach übernehmen, ohne sie neu implementieren zu müssen. Anders ist es allerdings hier: die Konstruktoren der abgeleiteten Tiere haben eine andere Konstruktorsignatur: sie nehmen keine Beinanzahl. Damit müssen wir einen neuen Konstruktor implementieren und den passenden vererbten aufrufen. Da gibt es keinen Weg drumrum.
+DeathRipper88 Ich verstehe die Frage nicht so recht. Du meinst den Parameter der Funktion bellen()? Wenn ja: an diesen Parameter kann alles übergeben werden, was ein Hund ist (ergo: Hund-Objekte oder Objekte aller abgeleiteten Klassen). In main() übergebe ich einen Labrador, der laut Ableitungsbaum ein Hund ist. bellen() sieht einen Hund. Ob das jetzt ein Labrador oder sonst irgendwas anderes ist, ist dieser Funktion egal. Hauptsache es ist ein Hund, also von Hund abgeleitet.
Die Klasse hat einen explizit implementierten Standardkonstruktor (direkt unter dem Keyword "public"). Den braucht sie auch, da die Basisklasse einen Konstruktor mit Parameter (und damit keinen generierten Standardkonstruktor mehr) hat. Würde man nun versuchen, die abgeleitete Klasse ohne Konstruktor zu implementieren, dann wüsste der Compiler nicht, welchen Konstruktor der Basisklasse er mit welchen Parametern aufrufen soll und verweigert die Arbeit. In dem Fall hier implementiert Hund einen Standardkonstruktor, der seine Basisklasse mit 4 als Parameterwert aufruft, da ich annehme, dass alle Hunde 4 Beine haben.
Die Klasse hat einen explizit implementierten Standardkonstruktor (direkt unter dem Keyword "public"). Den braucht sie auch, da die Basisklasse einen Konstruktor mit Parameter (und damit keinen generierten Standardkonstruktor mehr) hat. Würde man nun versuchen, die abgeleitete Klasse ohne Konstruktor zu implementieren, dann wüsste der Compiler nicht, welchen Konstruktor der Basisklasse er mit welchen Parametern aufrufen soll und verweigert die Arbeit. In dem Fall hier implementiert Hund einen Standardkonstruktor, der seine Basisklasse mit 4 als Parameterwert aufruft, da ich annehme, dass alle Hunde 4 Beine haben.
Hallo! Welchen Grund gibt es eigentlich, das Schlüsselwort const erst nach dem Funktionsnamen bzw. dem Variablentyp zu schreiben? Ich kann mich noch erinnern, dass du in einem früheren Video gesagt hast, du schreibst lieber int const var statt const int var. Aber warum? Da ich es nur anders kenne, ist es vor allem bei Funktionen sehr schwierig zu erkennen, was da jetzt konstant sein soll.
***** Ich merk's mir immer so: const wirkt immer auf den Teil direkt *links* von sich selbst. Außer, wenn es ganz links steht. Dann wirkt es auf den Teil direkt rechts daneben. Ein einfaches Beispiel: const int * v1 und int const * v2 sind das gleiche, aber int * const v3 ist was anderes. Die ersten beiden sind variable Pointer auf einen konstanten Integer, heißt: die Pointer dürfen verändert werden und woanders hinzeigen, aber der Integer, auf den sie zeigen, darf nicht geschrieben werden. v1 = &integer_variable und v2 = &integer_variable sind zulässig. Sie setzen ja nur die Pointer um. *v1 = 10 ist verboten: das würde den Integer selbst schreiben. Bei v3 ist es andersrum: *v3 = 10 ist erlaubt, der Integer ist nicht konstant. v3 = &integer_variable ist allerdings verboten: der Pointer v3 muss nach der Initialisierung gleich bleiben und wird immer auf die gleiche Stelle im Speicher zeigen. Die schärfste Variante ist int const * const: ein konstanter Pointer auf eine konstante Stelle im Speicher. Speziell in Kombination mit Pointern ist es eben wichtig, die const-Specifier von rechts nach links zu lesen. Deswegen bevorzuge ich diese Variante generell. Allerdings ist mir bewusst, dass es einen sehr großen Teil der C++-Welt (den Standard eingeschlossen) gibt, der das anders bevorzugt. Lesen und schreiben kann ich je nach Projekt, an dem ich arbeite, natürlich beides.
Deine C++ Videos sind mit Abstand die besten auf UA-cam, ich lese gerade ein C++ Buch und manchmal versteh ich halt etwas nicht... der erste Gedanke ist dann Bytes'n'Objects :D !
@Bytes'n'Objects: Danke für die sehr guten Videos. Kannst du den Source nochmal zur Verfügung stellen? Gerne auch gegen ne Kaffeespende ;)
In der Dackel Klasse greift dann der Standartkonstruktor? Könnte ich dem Dackel auch fünf Beine geben oder geht das nicht weil er von dem Hund abgeleitet wurde und der keine Parameter annimmt...?
Dackel kann keine Konstruktorparameter nehmen, da er nur über den implizit implementierten Defaultkonstruktor verfügt. Das hat mit der Ableitung von Hund nur bedingt zu tun, sondern mit dem implizit vorhandenen Konstruktor, der vom Compiler implementiert wird, wenn sonst keiner da ist.
Eine Frage zum Vererben des Konstruktor. Warum muss ich jedes mal bei einer abgeleiteten Klasse den Konstruktor der Basis Klasse angeben. Könnte man das umgehen?
Kommt darauf an. Mit C++11 kommt Konstruktorvererbung dazu. Dann kann man mit using Base::Base die Basiskonstruktoren einfach übernehmen, ohne sie neu implementieren zu müssen. Anders ist es allerdings hier: die Konstruktoren der abgeleiteten Tiere haben eine andere Konstruktorsignatur: sie nehmen keine Beinanzahl. Damit müssen wir einen neuen Konstruktor implementieren und den passenden vererbten aufrufen. Da gibt es keinen Weg drumrum.
Was ist mit der Referenz h? Wie kann man sie ohne Definition aufrufen? weil Hund h im Main nicht Definiert ist
+DeathRipper88 Ich verstehe die Frage nicht so recht. Du meinst den Parameter der Funktion bellen()? Wenn ja: an diesen Parameter kann alles übergeben werden, was ein Hund ist (ergo: Hund-Objekte oder Objekte aller abgeleiteten Klassen). In main() übergebe ich einen Labrador, der laut Ableitungsbaum ein Hund ist. bellen() sieht einen Hund. Ob das jetzt ein Labrador oder sonst irgendwas anderes ist, ist dieser Funktion egal. Hauptsache es ist ein Hund, also von Hund abgeleitet.
Die Klasse "Hund" hat ja keinen expliziten Konstruktor. Wird dann für Hund und alle geerbten Klassen jeweils der Standard-Konstruktor aufgerufen?
Die Klasse hat einen explizit implementierten Standardkonstruktor (direkt unter dem Keyword "public"). Den braucht sie auch, da die Basisklasse einen Konstruktor mit Parameter (und damit keinen generierten Standardkonstruktor mehr) hat. Würde man nun versuchen, die abgeleitete Klasse ohne Konstruktor zu implementieren, dann wüsste der Compiler nicht, welchen Konstruktor der Basisklasse er mit welchen Parametern aufrufen soll und verweigert die Arbeit. In dem Fall hier implementiert Hund einen Standardkonstruktor, der seine Basisklasse mit 4 als Parameterwert aufruft, da ich annehme, dass alle Hunde 4 Beine haben.
Die Klasse hat einen explizit implementierten Standardkonstruktor (direkt unter dem Keyword "public"). Den braucht sie auch, da die Basisklasse einen Konstruktor mit Parameter (und damit keinen generierten Standardkonstruktor mehr) hat. Würde man nun versuchen, die abgeleitete Klasse ohne Konstruktor zu implementieren, dann wüsste der Compiler nicht, welchen Konstruktor der Basisklasse er mit welchen Parametern aufrufen soll und verweigert die Arbeit. In dem Fall hier implementiert Hund einen Standardkonstruktor, der seine Basisklasse mit 4 als Parameterwert aufruft, da ich annehme, dass alle Hunde 4 Beine haben.
Hallo!
Welchen Grund gibt es eigentlich, das Schlüsselwort const erst nach dem Funktionsnamen bzw. dem Variablentyp zu schreiben?
Ich kann mich noch erinnern, dass du in einem früheren Video gesagt hast, du schreibst lieber int const var statt const int var. Aber warum? Da ich es nur anders kenne, ist es vor allem bei Funktionen sehr schwierig zu erkennen, was da jetzt konstant sein soll.
***** Ich merk's mir immer so: const wirkt immer auf den Teil direkt *links* von sich selbst. Außer, wenn es ganz links steht. Dann wirkt es auf den Teil direkt rechts daneben. Ein einfaches Beispiel:
const int * v1 und int const * v2 sind das gleiche, aber int * const v3 ist was anderes. Die ersten beiden sind variable Pointer auf einen konstanten Integer, heißt: die Pointer dürfen verändert werden und woanders hinzeigen, aber der Integer, auf den sie zeigen, darf nicht geschrieben werden. v1 = &integer_variable und v2 = &integer_variable sind zulässig. Sie setzen ja nur die Pointer um. *v1 = 10 ist verboten: das würde den Integer selbst schreiben. Bei v3 ist es andersrum: *v3 = 10 ist erlaubt, der Integer ist nicht konstant. v3 = &integer_variable ist allerdings verboten: der Pointer v3 muss nach der Initialisierung gleich bleiben und wird immer auf die gleiche Stelle im Speicher zeigen. Die schärfste Variante ist int const * const: ein konstanter Pointer auf eine konstante Stelle im Speicher.
Speziell in Kombination mit Pointern ist es eben wichtig, die const-Specifier von rechts nach links zu lesen. Deswegen bevorzuge ich diese Variante generell. Allerdings ist mir bewusst, dass es einen sehr großen Teil der C++-Welt (den Standard eingeschlossen) gibt, der das anders bevorzugt. Lesen und schreiben kann ich je nach Projekt, an dem ich arbeite, natürlich beides.