Kassiopeia schrieb:
> Vielen Dank,
>
> ist eigentlich einleuchtend. Aufgrund der Tatsache, dass es unter AVR
> bisher funktioniert (und in etliche Bibliotheken auch so gemacht wird),
> habe ich den Aufruf anderer Klassen in der Initialisierungsfrage nicht
> kritisch genug hinterfragt!
>
> Zum Konstruktoraufruf:
>
> Müsste ein Funktionsprototyp nicht einen vorangestellten Typ (und sei es
> void ) haben?
hat er doch.
Es gibt keinen syntaktischen Unterschied zwischen
oder
und
void, int bzw. libTWI ist der Datentyp des Rückgabewertes, foo. bzw.
mySensor ist der Name der Funktion und die () bedeuten, dass die
Funktion keine Argumente nimmt.
Das sieht aus wie eine Funktionsdeklaration (ein Protoyp) und damit ist
es auch eine.
Das hier
kann keine Funktionsdeklaration sein. Denn in der Argumentliste einer
Funktion können keine Zahlen auftauchen. Da müsste ein Datentyp stehen,
so wie in
1 | libTWI mySensor( int a );
|
dann wäre das eine Funktionsdeklaration. Aber so
passt das nicht auf eine Funktionsdeklaration, also ist es auch keine.
Das vereinbart tatsächlich ein Objekt namens mySensor, welches vom
Datentyp libTWI ist, und dessen Konstruktor zur Initialisierung 100
mitkriegt.
> Nur Konstruktoren sind eigentlichen typlos.
Davon ist aber nicht die Rede.
Dein Protoyp ist der Prototyp einer freistehenden Funktion
1 | libTWI mySensor()
|
2 | {
|
3 | libTWI dasObjekt;
|
4 |
|
5 | // mach irgendwas
|
6 |
|
7 | return dasObjekt;
|
8 | }
|
Studier noch mal dein C Buch zum Thema Funktionsdeklaration bzw.
Prototyp.
Ein Protoyp ist die Information für den Compiler, wie eine Funktion
aussieht, welchen Rückgabewert sie hat und welche Argumente sie nimmt,
damit der Compiler diese Daten kennt ohne die eigentliche Funktion
gesehen zu haben.
So wie in
1 | void bar(); // Protoyp der Funktion. Die Funktion ist zu diesem Zeitpunkt noch nicht bekannt.
|
2 | // Damit sie aber aufgerufen werden kann, teilen wir dem Compiler
|
3 | // die für den Aufruf wesentlichen Details mit
|
4 |
|
5 | void foo()
|
6 | {
|
7 | bar(); // Da der Compiler den Protoyp gesehen hat, kann er diesen Aufruf
|
8 | // kontrollieren. Er weiss, dass
|
9 | // * es eine Funktion namens bar gibt
|
10 | // * die Funktion keine Argumente nimmt
|
11 | // * und nichts liefert
|
12 | // Dieser Funktionsaufruf passt dazu, daher ist alles in Ordnung
|
13 |
|
14 | baz(); // wohingegen der Compiler von einer Funktion baz() noch nie
|
15 | // etwas gehört hat. Das setzt also einen Fehler
|
16 | }
|
17 |
|
18 | void bar()
|
19 | {
|
20 | // und hier ist sie dann tatsächlich, die Funktion bar
|
21 | }
|
22 |
|
23 | void baz()
|
24 | {
|
25 | // das ist zwar schön, dass es die Funktion baz tatsächlich gibt, hilft
|
26 | // abere nicht weiter. Der Compiler liest den Quelltext von oben nach unten.
|
27 | // Wenn hier baz zum ersten mal auftaucht, dann ist das zu spät für den Aufruf
|
28 | // dieser Funktion da oben. Entweder muss die Funktion nach oben verschoben
|
29 | // werden, vor foo ... oder es muss ein Protoyp an den Anfang kommen, der
|
30 | // den Compiler darüber informiert, dass es diese Funktion tatsächlich gibt
|
31 | // und welche Signatur sie hat
|
32 | }
|
> Bei nochmaligem Nachlesen habe ich den Aufruf mit leerer
> runder Klammer in den Stroustrup hineininterpretiert.
Sei ein bischen vorsichtig.
Es gibt einen kleinen subtilen Unterschied zwischen
1 | myClass * pA = new myClass;
|
und
1 | myClass * pA = new myClass();
|
Je nach genauem Aufbau von myClass, ob sie eine sog. POD ist oder nicht,
passieren hier subtil unterschiedliche Dinge.
Lass dich darauf nicht ein! Das schafft nur Verwirrung. Zumal die
meisten C++ Programmierer von einer POD (Plain Old Datatype) noch nie
etwas gehört haben und nicht wissen, dass es da je nach Schreibweise
kleine Unterschiede in der Initialisierung gibt.