• Nie Znaleziono Wyników

Konwersja typu w Cpp - prezentacja

N/A
N/A
Protected

Academic year: 2021

Share "Konwersja typu w Cpp - prezentacja"

Copied!
19
0
0

Pełen tekst

(1)

Języki programowania III

C++

Konwersje typów

Wykład dla 2-go roku Informatyki Stosowanej

Wydział Fizyki i Informatyki Stosowanej UŁ

(2)

W C++ w stosunku do C została zaostrzona kontrola typów.

Główna zmiana dotyczy wskaźników na typ void*.

W C były one zupełnie bezkarne i można było przydzielać wskaźniki void* do każdych innych.

W C++ są na równi z innymi typami.

Teoretycznie kod napisany w C

(3)

Kod w C, bez problemu skompilowany w kompilatorze tegoż języka:

int* wskaznik = malloc(sizeof(int));

nie zostanie skompilowany w kompilatorze C++, z powodu zaostrzonej kontroli typów, dlatego w C++ należey posłużyć się konwersją do docelowego typu wskaźnikowego:

(4)

int zmienna_calkowita = int(zmienna_rzeczywista);

W C++ nadal można używać takiego rzutowania,

jest ono nazywane "rzutowaniem w stylu C".

Oprócz tego C++ oferuje

"rzutowanie w stylu funkcyjnym":

W języku C rzutowanie wyglądało w następujący sposób:

int zmienna_calkowita = (int)zmienna_rzeczywista;

(5)

C++ wprowadza inny sposób zapisu.

Dodatkowo rzutowanie podzielono na cztery typy:

static_cast

const_cast

reinterpret_cast

dynamic_cast

(6)

C++ wprowadza inny sposób zapisu.

Dodatkowo rzutowanie podzielono na cztery typy: 1. Proste rzutowanie

static_cast

const_cast

2. Rzutowanie ze zmiennych z modyfikatoremconst i volatile na zmienne bez tych modyfikatorów

static_cast – najczęściej używane.

Gdy konwersja "implicit" traci informację lub kompilator produkuje "worningi". Usuwanie niejednoznaczności.

const_cast – dla zastosowania lub usunięcia

(7)

C++ wprowadza inny sposób zapisu.

Dodatkowo rzutowanie podzielono na cztery typy:

reinterpret_cast

3. Niebezpieczne rzutowania, które zmieniają zupełnie sens interpretacji bitów w zmiennych

dynamic_cast

4. Rzutowanie wskaźników na obiekty

dynamic_cast – używając polimorficznych wskaźników lub referencji

dla zmiany (do góry lub do dołu) hierarchii klas. Gdy dynamic_cast wykonuje sprawdzanie,

czy typ obiektu jest zgodny z oczekiwanym, jeśli nie – zwracany NULL

reinterpret_cast – jest używane przy konwersji typów niepowiązanych,

np. niepowiązane wskaźnikim i referencje

(8)

Sposób użycia nowych operatorów rzutowania:

int zmienna_całkowita = static_cast<int>(zmienna_rzeczywista);

(9)

Static_cast :

• do konwersji podstawowych typów liczbowych, np. int na float.

• do konwersji zdefiniowanych przez użytkownika.

• do konwersji wskaźnika na obiekt klasy pochodnej na wskaźnik na obiekt klasy podstawowej (tak zwane rzutowanie do góry hierarchii dziedziczenia).

• do konwersji wskaźnika na obiekt klasy podstawowejna wskaźnik na obiekt klasy pochodnej (tak zwane rzutowanie w dół hierarchii).

(10)

Do czego static_cast nie służy:

* Do rzutowania wskaźników na różne typy,

jeśli nie ma specjalnie zdefiniowanej konwersji między tymi wskaźnikami.

Przykładowo nie skompiluje się static_cast<int*>(i), jeśli zmienna i jest typu unsigned int*

Nie uda się też rzutowanie ze wskaźnika na typ stały

(z modyfikatorem const) na wskaźnik na typ niestały.

* Do dynamicznego sprawdzania, czy rzutowanie mogłoby się powieść.

Nie miałoby to sensu,

(11)

Poprawne

użycie static_cast:

#include <iostream>

int main() {

int liczba = 5, liczba2 = 2;

std::cout << "5 / 2 int(bez rzutowania): " << liczba / liczba2 << std::endl; std::cout << "5/2 float(static_cast): " <<

static_cast<float>(liczba) / static_cast<float>(liczba2)<< std::endl; return 0;

(12)

Niepoprawne

użycie static_cast:

#include <iostream> int main() {

std::string str = "ciąg";

std::cout << "string --> char: " << static_cast<char>(str) << std::endl; return 0;

(13)

Inne Cechy static_cast:

• wyrażenia, które nie dokonują żadnej konwersji mogą być również opisane operatorem static_cast,

np. int i=static_cast<int>(8);

można to bezpiecznie usunąć z kodu nie korzystającego z szablonów.

• Wszędzie, gdzie mówi się o wskaźnikach, można mówić oreferencjach. Obowiązują je te same reguły.

Działanie rzutowania static_cast zależy od informacji o typach dostępnych czasie kompilacji.

Stąd słowo "static" w "static_cast".

Kompilator nie dodaje "z własnej inicjatywy" kodu binarnego,

więc static_cast można używać również w tzw. wąskich gardłach programu. (jakiś kod oczywiście jest dodawany przez kompilator)

(14)

const_cast

Syntax:

T const_cast<T> (object);

dla "usunięcia"const lub volatile z obiektu.

Typ targetu musi być tego samego typu co źródło.

Typ T musi być typem wskaźnikowym lub referowanym.

Np. użycie const_cast usuwa kwalifikator const z obiektu: class Foo {

public:

void func() {}

// a non-const member function

};

void someFunction( const Foo& f ) {

f.func();

// compile error: cannot call a non-const

// function on a const reference

Foo &fRef = const_cast<Foo&>(f);

(15)

dynamic_cast

Syntax:

T& dynamic_cast<T&> (object); T* dynamic_cast<T*> (object);

Dla konwersji obiektu ze wskaźnika lub referencji jednego typu do innego typu.

Przy próbie konwersji do wskaźnika typu, który nie jest typem aktualnym – wynikiem rzutowania będzie NULL.

(16)

dynamic_cast

struct A { virtual void f() { } }; struct B : public A { }; struct C { }; void f () { A a; B b; A* ap = &b;

B* b1 = dynamic_cast<B*> (&a); // NULL, ponieważ 'a' nie jest typu 'B' B* b2 = dynamic_cast<B*> (ap); // 'b'

C* c = dynamic_cast<C*> (ap); // NULL.

A& ar = dynamic_cast<A&> (*ap); // Ok. B& br = dynamic_cast<B&> (*ap); // Ok.

C& cr = dynamic_cast<C&> (*ap); // std::bad_cast }

(17)

Funkcja Konwersji

Np. class Y { int b; public: operator int(); }; Y::operator int() { return b; }

void f(Y obj) {

int i = int(obj); int j = (int)obj; int k = i + obj; }

(18)

Wszystkie trzy konwersje w funkcji f(Y) użyją funkcji konwertującej Y::operator int().

Classes, enumerations, typedef names, function types, or array types cannot be declared or defined in the conversion_type.

Można użyć funkcji konwertującej dla konwersji obiektu typu A do typu A,

do typu bazowego klasy A lub do void.

Funkcja konwertująca nie ma argumentów i zwraca typ będący typem konwertowanym. Funkcja konwertująca nie może być dziedziczona.

(19)

Cytaty

Powiązane dokumenty

Człowiek wobec świata • podręcznik NOWE Słowa na

krótkie wprowadzenie, pokaz z wykorzystaniem projektora, praca z podręcznikiem, ćwiczenia;.

W terminie 7 dni od dnia podania do publicznej wiadomości listy dzieci przyjętych i dzieci nieprzyjętych, rodzic dziecka może wystąpić do komisji rekrutacyjnej z wnioskiem o

7. Do postępowania uzupełniającego stosuje się przepisy niniejszego regulaminu. W pracach komisji jako obserwatorzy mogą brać udział przedstawiciele Organu Prowadzącego

Regulamin nie dotyczy przyjęcia kandydata do szkoły w trakcie roku szkolnego. W tym przypadku decyzję o przyjęciu do szkoły podejmuje dyrektor szkoły. Zapisy

Prawo oświatowe (z którego wynika, że dane osobowe kandydatów zgromadzone w celach postępowania rekrutacyjnego oraz dokumentacja postępowania rekrutacyjnego

W przypadku uzyskania przez grupę kandydatów równorzędnych wyników, komisja rekrutacyjna, ustalając kolejność kwalifikacji, bierze pod uwagę miejsce szkoły na liście

Wyrażam zgodę / Nie wyrażam zgody* na publikację na terenie szkoły, na stronie internetowej szkoły oraz w materiałach informacyjnych opisujących działania