Kiedy należy używać typedef w C++?

W moich latach programowania w C++ (MFC) nigdy nie czułem potrzeby używania typedef, więc naprawdę Nie wiem, do czego jest on używany. Gdzie mam go używać? Czy są jakieś realne sytuacje, w których preferowane jest użycie typedef? A może to bardziej słowo kluczowe specyficzne dla języka C?

 60
Author: ZhiXingZhe - WangYuQi, 2009-02-05

12 answers

Metaprogramowanie Szablonu

typedef jest konieczne dla wielu metaprogramowanie szablonu -- ilekroć klasa jest traktowana jako "funkcja typu kompilacji czasu", typedef jest używana jako "wartość typu kompilacji czasu" w celu uzyskania typu wynikowego. Np. rozważ prostą metafunkcję konwersji typu wskaźnika na typ bazowy:

template<typename T>
struct strip_pointer_from;

template<typename T>
struct strip_pointer_from<T*> {   // Partial specialisation for pointer types
    typedef T type;
};

Przykład: wyrażenie typu strip_pointer_from<double*>::type oblicza się na double. Zauważ, że metaprogramowanie szablonów nie jest powszechnie stosowane poza rozwój biblioteki.

Upraszczanie Typów Wskaźników Funkcji

typedef jest pomocne do nadawania krótkiego, ostrego aliasu skomplikowanym typom wskaźników funkcji:

typedef int (*my_callback_function_type)(int, double, std::string);

void RegisterCallback(my_callback_function_type fn) {
    ...
}
 77
Author: j_random_hacker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-23 20:01:21

W książce Bjarne stwierdza, że można użyć typedef do rozwiązywania problemów z przenośnością między systemami, które mają różne rozmiary całkowite. (jest to parafraza)

Na maszynie gdzie sizeof (int) wynosi 4 możesz

typedef int int32;

Następnie użyj int32 wszędzie w kodzie. Gdy przejdziesz do implementacji C++ gdzie sizeof (int) wynosi 2, możesz po prostu zmienić typdef

typedef long int32;

I twój program nadal będzie pracował nad nową implementacją.

 29
Author: Jason Punyon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-05 15:20:41

Użyj ze wskaźnikiem funkcji

Hide Function Pointer Declarations With a typedef

void (*p[10]) (void (*)() );

Tylko nieliczni Programiści potrafią stwierdzić, że p jest "tablicą 10 wskaźników do funkcji zwracającej void i pobierającej wskaźnik do innej funkcji, która zwraca void i nie pobiera argumentów."Kłopotliwa składnia jest prawie nie do odczytania. Można go jednak znacznie uprościć, korzystając z deklaracji typedef. Najpierw należy zadeklarować typedef dla " wskaźnika do funkcji zwracającej void i przyjmującej no argumenty " jak następuje:

  typedef void (*pfv)();

Następnie zadeklaruj kolejny typedef dla "wskaźnika do funkcji zwracającej void i pobierającej pfv" na podstawie typedefu, który wcześniej zadeklarowaliśmy:

 typedef void (*pf_taking_pfv) (pfv);

Teraz, gdy stworzyliśmy Typ pf_taking_pfv jako synonim nieporęcznego "wskaźnika do funkcji zwracającej void i przyjmującej pfv", deklarowanie tablicy 10 takich wskaźników jest bardzo proste:

  pf_taking_pfv p[10];

Od

 16
Author: yesraaj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-05 15:12:58

Dla przykładu: kontenery STL.

 typedef std::map<int,Froboz> tFrobozMap;
 tFrobozMap frobozzes; 
 ...
 for(tFrobozMap::iterator it=frobozzes.begin(); it!=map.end(); ++it)
 {
     ...
 }

Nie jest niczym niezwykłym nawet używanie typedefów takich jak

typedef tFrobozMap::iterator tFrobozMapIter;
typedef tFrobozMap::const_iterator tFrobozMapCIter;

Inny przykład: używanie współdzielonych wskaźników:

class Froboz;
typedef boost::shared_ptr<Froboz> FrobozPtr;

[update] Jak w komentarzu-gdzie je umieścić?

Ostatni przykład-użycie shared_ptr - jest proste: są prawdziwym materiałem nagłówka-lub przynajmniej nagłówkiem do przodu. Potrzebujesz deklaracji forward dla shared_ptr i tak, a jedną z jej deklarowanych zalet jest to, że jest Bezpieczna do użycia z przednim deklem.

Ująć to inaczej: jeśli istnieje shared_ptr, prawdopodobnie powinieneś używać tego typu tylko poprzez shared_ptr, więc oddzielanie deklaracji nie ma większego sensu.

(Tak, xyzfwd.h to ból. Używałbym ich tylko w hotspotach-wiedząc, że hotspoty są trudne do zidentyfikowania. Blame the C++ compile+link model...)

Typedefs kontenera zwykle używam tam, gdzie zmienna kontenera jest zadeklarowana - np. lokalnie dla lokalnego var, jako członkowie klasy, gdy rzeczywistą instancją kontenera jest członek klasy. Działa to dobrze, jeśli rzeczywisty typ kontenera jest szczegółem implementacji - nie powodując żadnych dodatkowych zależności.

Jeśli stają się częścią konkretnego interfejsu, są deklarowane razem z interfejsem, z którym są używane, np.

// FrobozMangler.h
#include "Froboz.h"
typedef std::map<int, Froboz> tFrobozMap;
void Mangle(tFrobozMap const & frobozzes); 

To staje się problematyczne, gdy typ jest elementem wiążącym między różnymi interfejsami - tzn. ten sam typ jest potrzebny wielu nagłówkom. Niektóre rozwiązania:

  • declare it wraz z zawartym typem (nadaje się do pojemników, które są często używane dla tego typu)
  • przenieś je do osobnego nagłówka
  • przenieś do oddzielnego nagłówka i uczyń z niego klasę danych, w której rzeczywisty kontener jest ponownie szczegółem implementacji

Zgadzam się, że te dwa ostatnie nie są takie świetne, użyłbym ich tylko wtedy ,gdy wpadnę w kłopoty (nie proaktywnie).

 16
Author: peterchen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-25 02:11:33

Typedef jest przydatny w wielu sytuacjach.

Zasadniczo pozwala na utworzenie aliasu dla typu. Kiedy / jeśli musisz zmienić typ, reszta kodu może pozostać niezmieniona(oczywiście zależy to od kodu). Na przykład powiedzmy, że chcesz iterować na wektorze c++

vector<int> v;

...

for(vector<int>::const_iterator i = v->begin(); i != v.end(); i++) {

// Stuff here

}

W przyszłości możesz pomyśleć o zmianie wektora z listą, ponieważ rodzaj operacji, które musisz na nim wykonać. Bez typedef musisz zmienić wszystkie wystąpienia wektora w Twoim kod. Ale jeśli napiszesz coś takiego:

typedef vector<int> my_vect;

my_vect v;

...

for(my_vect::const_iterator i = v->begin(); i != v.end(); i++) {

// Stuff here

}

Teraz wystarczy zmienić jeden wiersz kodu (tj. z "typedef vector<int> my_vect " na " typedef list<int> my_vect") i wszystko działa.

Typedef oszczędza również czas, gdy masz złożone struktury danych, które są bardzo długie do napisania (i trudne do odczytania)

 5
Author: Emiliano,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-05 15:12:19

Dobrym powodem do używania typedef jest to, że typ czegoś może się zmienić. Załóżmy na przykład, że na razie 16-bitowe ints nadają się do indeksowania niektórych zestawów danych, ponieważ w przewidywalnej przyszłości będziesz mieć mniej niż 65535 pozycji, a ograniczenia przestrzeni są znaczące lub potrzebujesz dobrej wydajności pamięci podręcznej. Jednak, jeśli nie masz możliwości użycia programu na zbiorze danych z ponad 65535 pozycji, chcesz być w stanie łatwo przełączyć się na szerszą liczbę całkowitą. Użyj typedef, a Ty trzeba to tylko zmienić w jednym miejscu.

 5
Author: dsimcha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-05 15:13:56

typedef pozwala nie tylko mieć alias dla złożonych typów, ale daje naturalne miejsce do dokumentowania typu. Czasami używam go do celów dokumentacyjnych.

Są też chwile, kiedy używam tablicy bajtów. Tablica bajtów może oznaczać wiele rzeczy. typedef ułatwia zdefiniowanie tablicy bajtów jako "hash32" lub "fileContent", aby uczynić mój kod bardziej czytelnym.

 4
Author: Ztyx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-19 00:28:08

Rzeczywiste zastosowania typedef:

  • zapewnienie przyjaznych aliasów dla długich szablonów typów
  • zapewnienie przyjaznych aliasów dla typów wskaźników funkcji
  • Zapewnienie lokalnych etykiet dla typów, np.:

    template<class _T> class A
    {
        typedef _T T;
    };
    
    template<class _T> class B
    {
        void doStuff( _T::T _value );
    };
    
 2
Author: moonshadow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-05 15:28:28

Istnieje kolejny przypadek użycia typedef, gdy chcemy włączyć Rodzaj kodu niezależnego od kontenera (ale nie do końca!)

Powiedzmy, że masz klasę:

Class CustomerList{

public:
    //some function
private:
    typedef list<Customer> CustomerContainer;
    typedef CustomerContainer::iterator Cciterator;
};

Powyższy kod zawiera wewnętrzną implementację kontenera za pomocą typedef i nawet jeśli w przyszłości kontener listy będzie musiał zostać zmieniony na vector lub deque, użytkownik klasy CustomerList nie musi się martwić o dokładną implementację kontenera.

Stąd typedef enkapsuluje i nieco pomaga nam napisać niezależny od kontenera kod

 2
Author: Imran Al Noor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-20 10:14:14

Ilekroć sprawia, że źródło jest jaśniejsze lub lepsze do odczytania.

Używam typedef w C# dla generics / templates. "NodeMapping" jest po prostu lepiej czytać/używać i rozumieć wtedy dużo " Dictionary". IMHO. Więc polecam go do szablonów.

 0
Author: Leonidas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-05 15:04:56

Typedef pozwala na elastyczność w klasie. Jeśli chcesz zmienić typ danych w programie, nie musisz zmieniać wielu lokalizacji, ale wystarczy zmienić jedno wystąpienie.

typedef <datatype example  int or double> value_type

Możesz podać nazwę nay zamiast value_type, ale value_type jest zwykle nazwą standardową.

Więc u można używać typedef jak

value_type i=0;     //same as a int or double i=0; 
 0
Author: sneha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-11 21:32:07

... i nie potrzebujesz Typedef do enum lub struktury.

A może ty?
typedef enum { c1, c2 } tMyEnum;
typedef struct { int i; double d; } tMyStruct;

Może być lepiej napisane jako

enum tMyEnum { c1, c2 }
struct  tMyStruct { int i; double d; };
Czy to prawda? A co z C?
 -1
Author: xtofl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-05 15:31:49