2015-04-16 8 views
75

Zum Beispiel einer Erklärung, wie das:Warum erlaubt uns C++, den Variablennamen bei der Deklaration einer Variablen in Klammern zu setzen?

int (x) = 0; 

Oder auch, dass:

int (((x))) = 0; 

ich auf das, weil in meinem Code stolperte ich ein Fragment ähnlich den folgenden, einen haben passiert:

struct B 
{ 
}; 

struct C 
{ 
    C (B *) {} 
    void f() {}; 
}; 

int main() 
{ 
    B *y; 
    C (y); 
} 

Offensichtlich wollte ich Objekt C konstruieren, die dann etwas nützliches in seinem Destruktor tun würde. Wie dem auch sei, der Compiler behandelt C (y); als eine Deklaration der Variablen y mit dem Typ C und gibt daher einen Fehler über y Neudefinition aus. Interessante Sache ist, dass, wenn ich es als C (y).f() oder als etwas wie C (static_cast<B*> (y)) schreibe, es wie beabsichtigt kompilieren wird. Die beste moderne Problemumgehung ist die Verwendung von {} im Konstruktoraufruf natürlich.

So wie ich später herausgefunden, ist es möglich, Variablen wie int (x) = 0; oder sogar int (((x))) = 0; zu deklarieren, aber ich habe noch nie jemanden gesehen, der solche Deklarationen tatsächlich verwendet. Ich bin also interessiert - was ist der Zweck einer solchen Möglichkeit, weil ich jetzt sehe, dass es nur den Fall ähnlich dem berüchtigten "ärgerlichsten Parse" schafft und nichts nützliches hinzufügt?

+0

Der "Zweck" der Möglichkeit ist wahrscheinlich, den Parser zu vereinfachen. – molbdnilo

+0

mögliches Duplikat von [Was ist der Zweck einer Deklaration wie int (x); oder int (x) = 10;] (http://stackoverflow.com/questions/26832321/what-is-the-purpose-of-a-declaration-like-int-x-or-int-x-10) – GSerg

+1

@GSerg Lustig, wie der Text meiner Frage auf die Frage von der zweiten Antwort in Ihrer verbundenen Frage antwortet, da ich das Beispiel zur Verfügung stelle, in dem das Erlauben solcher Deklarationen zu unerwarteten Ergebnissen führt :) – Predelnik

Antwort

75

Gruppierung.

Als besonderes Beispiel dazu, dass Sie eine Variable vom Typ Funktion wie

int f(int); 

Jetzt erklären können, wie würden Sie einen Zeiger auf so etwas erklären?

int *f(int); 

Nein, funktioniert nicht! Dies wird als eine Funktion interpretiert, die int* zurückgibt. Sie müssen in den Klammern hinzuzufügen, um es richtig zu machen analysiert:

int (*f)(int); 

Das gleiche Geschäft mit Arrays:

int *x[5]; // array of five int* 
int (*x)[5]; // pointer to array of five int 
+10

Und um die Antwort zu vervollständigen: den speziellen Fall zu verweigern, nach dem der Fragesteller fragt, würde eine spezielle Sonderfallregel erfordern. Die aktuelle Definition, wie '()' in einem Typ funktioniert, ist im gesamten Typ einheitlich. –

+0

So der Spezialfall gilt für die meisten Ärger Pars. Dies liegt daran, dass die Syntax für die Initialisierung von Variablen mit Konstruktorargumenten später hinzugefügt wurde (in Eile, denke ich?). – AnArrayOfFunctions

+1

@ FISOCPP Gut. . Ja. C++ kam nach C.. . – iheanyi

17

Es ist in der Regel Klammern in solchen Erklärungen verwenden darf, weil die Erklärung, aus dem syntaktische Sicht sieht immer wie folgt aus:

<front type> <specification>; 

Zum Beispiel in der folgenden Erklärung:

int* p[2]; 

Der "Fronttyp" ist int (nicht int*) und die "Spezifikation" ist * p[2].

Die Regel besteht darin, dass Sie im Abschnitt "Spezifikation" beliebig viele Klammern verwenden können, da sie manchmal nicht eindeutig voneinander zu trennen sind.Zum Beispiel:

int* p[2]; // array of 2 pointers to int; same as int (*p[2]); 
int (*p)[2]; // pointer to an array of 2 ints 

Der Zeiger auf ein Array ist ein seltener Fall, aber die gleiche Situation, die Sie mit einem Zeiger auf Funktion haben:

int (*func(int)); // declares a function returning int* 
int (*func)(int); // declares a pointer to function returning int 

Dies ist die direkte Antwort auf Ihre Frage. Wenn Ihre Frage bezieht sich auf die Aussage wie C(y), dann:

  • Put Klammern um den gesamten Ausdruck - (C(y)) und Sie bekommen, was Sie
  • wollte ein temporäres Objekt Diese Aussage tut nichts, aber sie schaffen, die nicht mehr zu Leben nach dieser Anweisung endet (ich hoffe, das ist, was Sie vorhatten).
+1

Wie ich bereits erwähnt habe, war es zunächst etwas im Destruktor, ich denke, es ist ziemlich normal, wenn man eine gewisse Anzahl von "Verkettungen" hat. Funktionen zum Einstellen einiger Parameter und dann Ausführen aller Aufgaben im Destruktor. Vielen Dank für eine weitere Problemumgehung, ich schätze, das Schreiben von '{}' ist letztendlich die beste Lösung. – Predelnik

+4

Versuchen Sie, Ihre eigene Grammatik zu vermeiden und die im Standard bereitgestellte zu verwenden. '' ist irreführend und falsch. Die Grammatik ist '' –

+0

Sie haben Recht - ich sah nicht in den Standard, wiederholte nur die Regel von meinem Kopf. Tatsächlich kann in C++ 11 die Rolle von '' auch mit dem Schlüsselwort 'auto' abgespielt werden, es ist also nicht immer ein Typ. – Ethouris