2009-06-04 11 views
10

Widziałem kod jak często następujące w jakiś kod C++ Patrzę na:Jaki jest cel wpisywania klasy w C++?

typedef class SomeClass SomeClass; 

jestem zakłopotany, co to faktycznie osiąga. Wygląda na to, że to niczego nie zmieni. Co to oznacza? A jeśli to coś pożytecznego, czy warto dodatkowego wysiłku?

+4

Może powinieneś zapytać tę osobę? zamiast prosić wszystkich, ale tę osobę. – DevinB

+0

Chciałem uzyskać consensus, jeśli rzeczywiście jest tego wart, a nie wyjaśnienie jednej osoby. –

+0

A facet rzeczywiście był w błędzie. "non-tag ukrywa nazwę znacznika w C++" - nie jest prawdziwe w C, ani prawdziwe w C++. Dla pewnej inspiracji przeczytaj ten raport o usterkach http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407 –

Odpowiedz

7

Zobacz poprzednią odpowiedź na pokrewne pytanie. To długi cytat z artykułu Dan Saks, który wyjaśnia tę kwestię tak wyraźnie, jak cokolwiek Natknąłem:

Difference between 'struct' and 'typedef struct' in C++?

Technika ta może zapobiec rzeczywistych problemów (choć co prawda rzadkich problemów).

To taniego ubezpieczenia - to zero kosztów w środowisku wykonawczym lub w przestrzeni kodu (jedynym kosztem jest kilka bajtów w pliku źródłowym), ale ochrona, jaką otrzymujesz, jest tak mała, że ​​nieczęsto zdarza się, że ktoś z niej korzysta konsekwentnie. Mam fragment kodu "nowej klasy", który zawiera typedef, ale jeśli faktycznie zakodowałem klasę od zera bez użycia tego fragmentu, prawie nigdy nie zawracam sobie głowy (lub nie pamiętam?), Aby dodać typedef.

Więc powiedziałbym, nie zgadzam się z większością opinii wydanych tutaj - warto umieszczenie tych typedefs w, ale nie na tyle, że dałbym każdemu (w tym ja) nie żal o umieszczenie ich w

.

poproszono mnie na przykład, jak nie o nazwę klasy typedef'ed może spowodować nieoczekiwane zachowanie - oto przykład podnoszone mniej więcej z artykułu Saks:

#include <iostream> 
#include <string> 

using namespace std; 

#if 0 // change to #if 1 to get different behavior 
     // imagine that this is buried in some header 
     // and even worse - it gets added to a header 
     //  during maintenance... 
string foo() 
{ 
    return "function foo... \n"; 
} 
#endif 

class foo 
{ 
public: 
    operator string() { 
     return "class foo...\n"; 
    } 
}; 

int main() 
{ 
    string s = foo(); 

    printf("%s\n", s.c_str()); 
    return 0; 
} 

Jeżeli deklaracja funkcja jest wykonana widoczne, zachowanie programu po cichu zmienia się, ponieważ nie ma konfliktu nazw między funkcją foo a klauzulą ss foo.

Jeśli jednak podasz "typedef class foo foo;", otrzymasz błąd czasu kompilacji zamiast cichej różnicy w zachowaniu.

+0

Musisz to zrobić Wiele rzeczy się na to wydarzyło, że mam ochotę powiedzieć, że na to zasłużyłeś! Numer jeden zapewniałby przeliczanie zamiast używania nazwanych funkcji (zawsze nie-nie, IMHO). –

+2

Operatory konwersji mogą być nie-nie, ale wcale nie są rzadkością. W każdym razie nie będę się spierał, że "tak wiele rzeczy musi pójść nie tak". Tak jak powiedziałem, nie jest to coś, na co nalegam w kodzie moim lub kogokolwiek innego. Ale chciałem wyjaśnić, dlaczego jest to w kodzie PO (to było pytanie w końcu) i wskazać, że typedef nie ma kosztów i nie powoduje problemów. W rzeczywistości sprawia, że ​​kompilatory działają trochę tak, jak oczekują tego ludzie - chociaż zaskoczyło mnie zachowanie niektórych kompilatorów w kodzie Adama. Myślę, że dokument związany z litb jest edukacyjny w tym względzie. –

+0

To naprawdę interesujące; odpowiedzi, które uzyskałem na to pytanie, cieszą mnie, że zadałem to pytanie tutaj. –

0

Wygląda na to, że komentarz próbuje powiedzieć, że typedef tworzy symbol SomeClass global w sposób, który uniemożliwia każdemu zadeklarowanie obiektu lokalnego o tej samej nazwie, który ukrywa oryginalny SomeClass.

Starałem się to z VC6 (a nie prawdziwy C++ Wiem, ale najlepszy mam ATM) i nie wydaje się, aby zrobić wiele. SomeClass jest nadal ukrywany przez lokalną deklarację o tej samej nazwie. Być może zmienia treść komunikatu o błędzie dla jakiegoś kompilatora, aby był bardziej przydatny.

-2

rozumiem koncepcji różnych nazw, które tagi i identyfikatory żyją, ale jest to naprawdę nawet warta od wpisując je?

nr

+6

(-1) Absolutnie bez wyjaśnienia ani uzasadnienia. Równie dobrze mogłem napisać "tak". a jedyną różnicą byłaby reputacja. – DevinB

+0

Nie podoba ci się moja odpowiedź (on przecież przedstawił uzasadnienie), napisz własną. –

0

Wydaje mi się twój kolega może nie w pełni ukończył C

W C, jeśli deklarują struct foo {int a;};, nie ma nic można nazwać tylko foo , ale raczej struct foo. W związku z tym, że to dość powszechne typedef struct foo jak foo.

Zostało to zmienione w C++, z powodów, które powinny być dość oczywiste.

+1

Jest to możliwe, ale tak naprawdę nie nazwałbym zachowania C "ukrywanie imienia". –

20

Zapobiega kod takiego od kompilacji:

class SomeClass { ... }; 
int SomeClass; 

Jest to całkowicie legalne C++, choć to straszny. Jeśli to zrobisz, wszelkie odniesienia do gołego SomeClass odnoszą się do zmiennej. Aby odnieść się do klasy, podczas każdego użycia musisz jednoznacznie powiedzieć: class SomeClass. Jeśli utworzysz typedef:

class SomeClass { ... }; 
typedef class SomeClass SomeClass; 
int SomeClass; 

Następnie flag kompilatora definicję int SomeClass jako błąd, jak to słusznie należy.

+0

Twój drugi przykład kompiluje się dla mnie (VC2005). –

+3

Problem z VC++ - wtedy nie powinien się on kompilować. –

+0

Interesujące, to faktycznie działa z jednym kompilatorem, którego używam (a nie z MSVC). – Dolphin

0

Naprawdę uszkodzony kompilator lub ktoś, kto nie wie, co robi, lub tak myślę.

+0

Albo ktoś, kto wie o czymś, o czym wielu ludzi nie wie ... –

6

Adam podał prawidłowy powód, aby to zrobić, ale w odniesieniu do pytania "Czy to jest warte zachodu", dałbym głośny "Nie!".Ewentualny Kod problemu:

class SomeClass { ... }; 
int SomeClass; 

zostanie złapany, gdy nieco później ktoś mówi:

SomeClass sc; 

Wprawdzie kompilator będzie wskazywać na „złą” linii, ale coś takiego zdarza się tak rzadko (Nie sądzę, że kiedykolwiek widziałem to w prawdziwym kodzie), że nie może usprawiedliwić lasu w pobliżu zbędnych typedef.

+0

Dzięki za odpowiedź na to pytanie, naprawdę tego chciałem się dowiedzieć. Nigdy wcześniej tego nie widziałem, więc miałem przeczucie, że nie byłoby tego warte. –

+0

Jeśli pominiesz typedef, nie zawsze będziesz mieć błąd, choć wprawdzie sytuacja byłaby rzadkością. Funkcja o tej samej nazwie co klasa może ukryć coś, co w innym przypadku byłoby konstruktorem klasy. –

+0

Czy możesz podać przykład tego - nie mogę sobie wyobrazić, jak to będzie możliwe. –