2015-04-16 20 views
75

Na przykład oświadczenie takie jak:Dlaczego C++ pozwala na otaczanie nazwy zmiennej w nawiasach podczas deklarowania zmiennej?

int (x) = 0; 

Albo nawet, że:

int (((x))) = 0; 

natknąłem się na to, ponieważ w moim kodu zdarzyło mi się mieć fragment podobny do następującego:

struct B 
{ 
}; 

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

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

Oczywiście chciałem zbudować obiekt o nazwie C, który następnie zrobiłby coś użytecznego w jego destruktorze. Jednak, jak to się dzieje, kompilator traktuje C (y); jako deklarację zmiennej y z typem C iw ten sposób drukuje błąd związany z redefinicją y. Interesujące jest to, że jeśli napiszę to jako C (y).f() lub jako coś takiego jak C (static_cast<B*> (y)), to skompiluje się zgodnie z przeznaczeniem. Najlepsze nowoczesne obejście to oczywiście użycie polecenia {} w wywołaniu konstruktora.

Jak już się zorientowałem, można zadeklarować zmienne takie jak int (x) = 0; lub nawet int (((x))) = 0;, ale nigdy nie widziałem nikogo, kto faktycznie używa takich deklaracji. Więc jestem zainteresowany - jaki jest cel takiej możliwości, ponieważ na razie widzę, że tworzy ona tylko przypadek podobny do osławionej "najbardziej irytującej analizy" i nie dodaje niczego użytecznego?

+0

"Celem" możliwości jest prawdopodobnie uproszczenie parsera. – molbdnilo

+0

możliwy duplikat [Jaki jest cel deklaracji takiej jak int (x); lub 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 Funny, jak tekst mojego pytania odpowiada na pytanie z drugiej odpowiedzi w połączonym pytaniu, ponieważ podam przykład, w którym zezwalanie na takie oświadczenia prowadzi do nieoczekiwanych rezultatów :) – Predelnik

Odpowiedz

75

Grupowanie.

Jako konkretny przykład, że można zadeklarować zmienną typu funkcji, takich jak

int f(int); 

Teraz, w jaki sposób zadeklarować wskaźnik do czegoś takiego?

int *f(int); 

Nie, nie działa! Jest to interpretowane jako funkcja zwracająca int*. Trzeba dodać w nawiasie, aby przeanalizować właściwą drogę:

int (*f)(int); 

taką samą ofertę z tablicami:

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

I aby ukończyć odpowiedź: niedopuszczenie do konkretnego przypadku, o który pyta pytający, wymagałoby specjalnej reguły. Aktualna definicja tego, jak '()' działa w typie, jest jednakowa w całym typie. –

+0

Tak więc przypadek specjalny odnosi się do najbardziej irytującej analizy. Jest tak, ponieważ składnia inicjalizacji zmiennych z argumentami konstruktora została dodana później (w pośpiechu, jak sądzę?). – AnArrayOfFunctions

+1

@ FISOCPP Cóż. . tak. C++ przyszedł po C.. . – iheanyi

17

Jest generalnie dozwolone używać nawiasów w takich deklaracji, ponieważ deklaracja, od składniowej punktu widzenia wygląda zawsze tak:

<front type> <specification>; 

na przykład, w następującym oświadczeniem:

int* p[2]; 

"Typ przedni" to int (nie int*), a "specyfikacja" to * p[2].

Zasadą jest, że można użyć dowolnej liczby nawiasów zgodnie z potrzebą w części "specyfikacja", ponieważ czasami są nieuniknione do ujednoznacznienia.Na przykład:

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

Wskaźnik do tablicy jest to rzadki przypadek, ale taka sama sytuacja masz ze wskaźnikiem do funkcji:

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

Jest to bezpośrednia odpowiedź na swoje pytanie. Jeśli pytanie jest o rachunku jak C(y), a następnie:

  • Put nawiasy wokół całego wyrazu - (C(y)) i dostaniesz to, czego chciał
  • To stwierdzenie nie robi nic, ale tworząc tymczasowy obiekt, który przestaje życie po zakończeniu tej instrukcji (mam nadzieję, że to jest to, co zamierzałeś zrobić).
+1

Jak już wspomniałem, początkowo robił coś w destruktorze, domyślam się, że to dość standardowa rzecz, gdy masz pewną liczbę "łańcuchów" funkcje do ustawiania niektórych parametrów, a następnie wykonywania wszystkich zadań w destruktorze. Jeszcze raz dziękuję za obejście tego problemu, ale domyślam się, że napisanie '{}' jest najbardziej poprawne. – Predelnik

+4

staraj się unikać tworzenia własnej gramatyki i korzystania z tej przewidzianej w standardzie. '' jest mylące i błędne. Gramatyka to < ' –

+0

Masz rację - nie spojrzałem w standard, po prostu powtórzyłem regułę z mojej głowy. Właściwie w C++ 11 rola ' może być również odtwarzana przez słowo kluczowe' auto', więc nie zawsze jest to typ. – Ethouris

Powiązane problemy