Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?
Autor: 'Pietrzuch'
Kurs C++

Unia w C++

[lekcja] Dokument omawia co to są unie i pokazuje jak je stosować.

Co to jest Unia?

Unia jest to tak jakby struktura zawierająca jedno miejsce w pamięci przeznaczone dla paru obiektów różnego typu. Wielkość unii zawsze jest równa miejscu zajmowanemu przez największy obiekt znajdujący się w unii. Tzn. deklarując unię zawierającą 3 zmienne int przydzielamy jej miejsce o wielkości jednej zmiennej int. Oczywiście nie możemy używać wszystkich zmiennych naraz, ponieważ mając do czynienia z unią zawierającą zmienne char i int będą po prostu w nich śmieci gdy korzystamy z innej zmiennej będącej w unii. Powtarzam, jeżeli nasza unia zawiera np. obiekt typu int i double i gdy aktualnie korzystamy z double(8B) to po odczytaniu wartości int(4B) bez uprzedniego zapisu do niej pokażą nam się zwykłe śmieci. Podkreślam, naraz używamy tylko jednego obiektu. Obrazek pierwszy ilustruje pamięć używaną przez unię.
Przykład reprezentacji danych w unii C++

Przykładowy program uzywający unii

Kod:
C/C++
#include <iostream>

using namespace std;

union unia //tak definiujemy unię
{
    float u_zm1;
    short int u_zm2;
};

int main()
{
    unia pierw_unia;
    pierw_unia.u_zm2 = 456;
    pierw_unia.u_zm1 = 123.45; //ostatnia operacja w unii bazuje na u_zm1;
    cout << "Zmienna aktualna w unii: " << pierw_unia.u_zm1 << " - u_zm1\n";
    cout << "Zmienna nie aktualna w unii: " << pierw_unia.u_zm2 << " - u_zm2\n";
    pierw_unia.u_zm1 = 123.45;
    pierw_unia.u_zm2 = 456; //ostatnia operacja w unii bazuje na u_zm2
    cout << "Zmienna aktualna w unii: " << pierw_unia.u_zm2 << " - u_zm2\n";
    cout << "Zmienna nie aktualna w unii: " << pierw_unia.u_zm1 << " - u_zm1\n";
}
Tłumaczenie:
C/C++
union unia //tak definiujemy unię
{
    float u_zm1;
    short int u_zm2;
};
Tak definiujemy unię. Jak widzisz budową podobna jest ona do struktury z tym, że poprawny dostęp mamy tylko do jednej zmiennej w danej chwili. Oczywiście unia zajmuje też mniej miejsca. W unii również możemy używać słów private, public. Jednak nie można użyć w niej słowa protected, a to dlatego że unia nie może mieć dziedzica.

Inicjalizacja unii

Podobnie jak w strukturze/klasie możesz sobie napisać konstruktor jednak nie będę tu tego omawiał, a w zamian za to opiszę tu użycie tzw. inicjalizacji zbiorczej.
Przykładowo to jest nasza unia:
C/C++
union nasza_unia
{
    char znak;
    float liczba;
};
A oto przykład jak inicjalizować unię.
C/C++
nasza_unia unia_01 = { b };
Zwróć uwagę że takie zapisy są błędne:
C/C++
nasza_unia unia_01 = { b , 20.34345 };
Zapis jest niepoprawny, gdyż pomimo że jest to inicjalizacja zbiorowa, to przecież unia ma jedno miejsce w pamięci dla paru obiektów i naraz może być używany tylko jeden.
C/C++
nasza_unia unia_01 = { 20.34345 }; //BLĄD!
Ten zapis jest niepoprawny. Dlatego iż tym sposobem możemy inicjalizować tylko pierwszy obiekt zapisany w unii, czyli w naszym przypadku tylko zmienną znak o typie char. Zwróć uwagę też na to iż posługujemy się nawiasami klamrowymi, nie zwykłymi.

Unia anonimowa

Unia anonimowa jest to taki typ unii gdzie nie wpisujemy jej nazwy. W takim razie nie posługujemy się kropką/strzałką gdy odnosimy się do unii. Przykładowa anonimowa unia:
C/C++
union
{
    char znak;
    float liczba;
};
I do takiej unii w programie odwołujemy się tak:
C/C++
znak = a ;
std::cout << znak;
Należy też pamiętać że nie możemy równocześnie zdefiniować drugiej zmiennej o takiej samej nazwie w tym samym obszarze kodu, a więc taki program jest błędny:
C/C++
#include <iostream>
char znak;
union
{
    char znak; //dwukrotna definicja obiektu znak – BŁĄD!
    float liczba;
};

int main()
{
    znak = a ; //kompilator nie wie do której zmiennej się odwołać
    std::cout << znak;
}
Na koniec dodam że taki kod:
C/C++
union
{
    char znak;
    float liczba;
} un_001;
oznacza to samo co:
C/C++
union nasza_unia
{
    char znak;
    float liczba;
};
nasza_unia un_001;
Więc pierwszy przykład (oczywiście drugi też) kodu nie jest unią anonimową, pomimo iż nie zawiera nazwy.
Gdy do unii musimy odnosić się operatorem ‘.’ bądź ‘->’ to wiedz że nie jest ona anonimową.
Poprzedni dokument Następny dokument
Konstruktor, destruktor i konstruktor kopiujący klasy Szablony funkcji