Variablendeklaration



  • Hallo,
    Wieder eine Grundsatzfrage, gegeben ist folgendes:

    class X{
    public:
    X(){ /*...*/ }
    //...
    }
    
    class Y{
    // ...
    public:
    Y(string sz){ /*...*/ }
    void function(X*x){ /*...*/ }
    }
    

    Nun habe ich folgende main():

    int main(){
    X x();
    Y y("sdf");
    
    Y.function(&x); // geht nicht
    }
    

    Das geht nicht, der Fehler:

    error: no matching function for call to 'Read::readFile(DataSet (*)())'

    Es muss in main heissen:

    X x;
    

    Nur warum? Was ist der Unterschied zwischen "X x();" und "X x;", ich dachte bei beidem wird eine "statische" Variable deklariert? Anscheinend nicht?
    Und was stellt denn X(*) fuer eine Struktur dar? 😕


  • Mod

    Fabeltier schrieb:

    Was ist der Unterschied zwischen "X x();" und "X x;", ich dachte bei beidem wird eine "statische" Variable deklariert? Anscheinend nicht?

    Was ist das?

    void x();
    

    und wo ist dann hier der Unterschied

    X x();
    

    Leider ist die Grammatik der Sprache hier nicht eindeutig - diese Mehrdeutigkeit wird dahin aufgelöst, dass immer dann, wo es sich (auch) um eine Deklaration handeln könnte, das Konstrukt als Deklaration (hier einer Funktion) angenommen wird. Solange die Klammern nicht leer sind, kann man zwischen Funktionsdeklaration und Konstruktoraufrufen leicht unterscheiden. Im ersten Falle steht in den Klammern eine Liste von Typen (optional mit Bezeichnern), im zweiten Falle eine Liste von Ausdrücken. Bei den leeren Klammern ist das nicht der Fall. Überaschend - für den Anfänger - ist das ganze wohl deshalb, weil C++ keine lokalen Funktionsdefinitionen erlaubt. Eine lokale Funktionsdeklaration dagegen sehr wohl (sie deklariert allerdings eine gewöhnliche Funktion, lediglich die deklarative Region ist stark beschränkt). Man kann annehmen, dass dieser Sprachteil anders funktionieren würde, wenn das Erbe von C nicht wäre.

    Problematisch ist das Ganze im Allgemeinen nicht. Für nicht-PODs wird der Defaultkonstruktor ohnehin aufgerufen. Bei PODs kann man auf jeden Fall auf Copyinitialisierung ausweichen, ohne Effizienzeinbußen befürchten zu müssen (der Compiler, der das nicht optimiert, gehört wirklich auf den Müll).



  • Überaschend - für den Anfänger - ist das ganze wohl deshalb, weil C++ keine lokalen Funktionsdefinitionen erlaubt.

    Was meinst du...ich mach mir über den Satz einige Zeit Gedanken aber ich verstehe ihn nicht ganz. Ich kann in jeder Funktion eine andere Funktion definieren und aufrufen. Was soll dieser Satz bedeuten? Vielleicht ist meine Kritik fehl am Platz aber bitte befreit mich aus der Gedankenmühle über die Bedeutung dieses Satzes...


  • Mod

    Crash_Override schrieb:

    Ich kann in jeder Funktion eine andere Funktion definieren und aufrufen.

    Beispiel?



  • Danke fuer die Antwort!

    Wenn der Compiler das als Funktionsdeklaration liest ist das Verhalten schon irgendwie verstaendlich - nur was fuer einen Sinn sollte es haben eine Funktion innerhalb einer anderen lediglich zu _deklarieren_?? Ausserdem funktioniert ein Konstruktoraufruf mit dem anderen Konstruktor ja auch auf die gleiche Art und Weise (lediglich noch mit zusaetzlichem Parameter).

    camper schrieb:

    Was ist das?

    void x();
    

    und wo ist dann hier der Unterschied

    X x();
    

    ...
    (der Compiler, der das nicht optimiert, gehört wirklich auf den Müll).

    gcc (GCC) 4.1.2 20061028 (prerelease) (Debian 4.1.1-19)

    Nja, vllt sollte ich da irgendein Flag setzen?! Mich hat es aber schon irgendwie gewundert, der Konstruktor sollte eigentlich schon erkannt werden, wenn es wirklich daran liegt. 🙄



  • Fabeltier schrieb:

    Wenn der Compiler das als Funktionsdeklaration liest ist das Verhalten schon irgendwie verstaendlich - nur was fuer einen Sinn sollte es haben eine Funktion innerhalb einer anderen lediglich zu _deklarieren_??

    Wie gesagt wurde, ist das ein Erbe von C - und über den Sinn und Unsinn einer solchen Konstruktion lässt sich vortrefflich streiten.

    Ausserdem funktioniert ein Konstruktoraufruf mit dem anderen Konstruktor ja auch auf die gleiche Art und Weise (lediglich noch mit zusaetzlichem Parameter).

    Und genau dieser zusätzliche Parameter macht den Unterschied - dieses Konstrukt ist nämlich nicht mehr als Funktionsdeklaration anzusehen (woraus unmittelbar folgt, daß der Compiler es korrekt als Variablen-Deklaration mit Ctor-Aufruf interpretiert).



  • Klingt logisch, eine Variable ist kein Typ - also kann ein Konstruktoraufruf mit einem Parameter keine Deklaration sein. Dass man den Defaultkonstruktor explizit nicht aufrufen darf, also mit Klammern, muss man sich wohl einfach mal merken (als Anfaenger 🙂 ).

    Danke fuer die Antworten!


Anmelden zum Antworten