Typy rozróżnialne

2007-11-28 10:11

W większości języków możemy zdefiniować nową nazwę dla istniejącego typu danych; nazywa się ją zwykle aliasem. I tak na przykład w C/C++ jest to możliwe za pomocą słowa kluczowego typedef. Analogicznie w Delphi mamy od tego słowo kluczowe type:
[delphi]type TMyInt = Integer;[/delphi]
Tak powstały typ TMyInt jest faktycznie tylko aliasem. Zmienne należące do tego typu są bowiem całkowicie kompatybilne ze zmiennymi zwykłego typu całkowitego Integer. W razie potrzeby konwersja między nimi może bez problemu zachodzić w obie strony.

Jeżeli jednak użylibyśmy deklaracji w formie:
[delphi]type TMyInt = type Integer;[/delphi]
wówczas TMyInt byłby już zupełnie innym typem niż Integer. Mimo że oba mogłyby przechowywać wartości tego samego rodzaju (liczby całkowite) i z tego samego zakresu, konwersje między nimi wymagałyby rzutowania.
Można by sądzić, że tworzenie takich typów rozróżnialnych “na siłę” jest bezcelowe. Zauważmy jednak, że typy wyliczeniowe (deklarowane przez enum) są przecież także w gruncie rzeczy liczbami z określonego zbioru. Najczęściej jednak nie chcemy, aby możliwa była niejawna konwersja między nimi a normalnymi typami liczbami. Wszystko dlatego, że w enumach liczby nie pełnią funkcji liczb, tylko identyfikatorów pewnych stanów.

Podobnie tutaj w przypadku TMyInt nie chodzi nam zapewne o liczby w sensie ich wartości, tylko o coś w rodzaju uchwytów – identyfikatorów obiektow. Kopalnią typów przeznaczonych do takiego właśnie celu jest oczywiście Windows API, zawierające tak znane i lubiane typy jak HWND, HINSTANCE, HDC, itd. Wszystkie one są w gruncie rzeczy liczbami 32-bitowymi, a mimo to nie są ze sobą kompatybilne. Gdyby API to było obiektowe, obiekty reprezentowane obecnie przez te uchwyty należałyby do różnych klas.
Efekt niezgodności uchwytów osiągnięto, deklarując ich typy nie jako aliasy na DWORD:

  1. typedef DWORD HWND;  // wszystkie tak określone typy będą ze sobą zgodne

lecz jako niezwiązane ze sobą typy wskaźnikowe:

  1. struct __HWND;
  2. typedef __HWND* HWND;

Można to uznać za dość pokrętną sztuczkę, ale na pewno jest ona lepsza niż tworzenie typu wyliczeniowego zawierającego nieco ponad 4 miliardy (232) nazwanych stałych ;]

Tags: , , ,
Author: Xion, posted under Programming »


2 comments for post “Typy rozróżnialne”.
  1. spaxio:
    November 28th, 2007 o 17:18

    Ja dawno temu też miałem taką potrzebę.

    struct STag1 {};
    struct STag2 {};
    typedef CSubstring SxString_t;
    typedef CSubstring SxKey_t;

    Dzięki takiemu zapisowi, przy wywoływaniu ‘strumieniowania’ moglem zdecydować, czy chce dodawac łańcuch zanków – traktowany jako klucz czy jako string. :)

  2. krajek:
    November 28th, 2007 o 20:11

    Wreszcie zrozumiałem sens takich konstrukcji. Zawsze mnie dziwiło jak ktoś tak sobie ‘utrudniał’ zycie. thx

Comments are disabled.
 


© 2017 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.