Ostatnio czytałem o narzędziu pozwalającym porównywać typy danych, czyli o operatorze typeid zaimplementowanym w RTTI. Postanowiłem przeczytać cały artykuł (http://www.google.pl/url?sa=t&source=we … azz42RQTag) o tym, żeby przy okazji dowiedzieć się czegoś więcej o klasie type_info i mam kilka innych pytań:
Pytanie 1.
Nie wiem o co chodziło dokładnie z tymi konstrukcjami programowymi - wiem, że np. nie jest sprawdzana legalność przy operacji np. odniesienie się do 77 el. tablicy, która ma el. 10 - ale nie wiem czemu tak się dzieje dokładniej. Po za tym jak można w cytacie przeczytać, jeżeli naruszymy system typów, program nie skompiluje się. Więc gdyby tą silną typizację zaimplementowano w C++ zamiast tej zwykłej kontroli statycznej to co by się zmieniło ? Np. taka legalność przy tablicach :?:
Pytanie 2.
Ta konwersja dynamiczna robiona operatorem dynamic_cast różni się od static_cast (konwersji statycznej), że jeżeli coś ze static_cast nie wypali - błąd kompilacji. Dynamic_cast zwraca po prostu adres wskaźnika lub NULL do wskaźnika. I nazywa się to konwersją dynamiczną tylko dlatego, że operator ten “uczy się jakby tej hierarchii”, ponieważ gdzieś w klasie jest funkcja wirtualna (bo musi być do tego) i jest jakby operatorem “polimorficznym” :?:
Pytanie 3.
Czy ktoś mógłby wytłumaczyć co robi w takim razie taka funkcja, bo na początku też mi przyszło do głowy, że zajmuje się hierarchiami :?:
Jeżeli chodzi o różnicę adresów to przychodzi mi do głowy tylko jeden pomysł. W tym artykule co dałem na początku link, jest napisane, że operator typeid zwraca obiekt klasy type_info. I wg mnie w tej funkcji before po prostu porównują dwa adresy:
746835 < 9824434
I teraz by ta funkcja zwróciła true, bo pierwszy obiekt typu type_info został utworzony wcześniej niż drugi, ponieważ komórka w pamięci gdzie on się znajduje ma adres mniejszy niż ten drugi obiekt. O to chodzi w tej funkcji :?:
Pytania są trochę duże, ale myślę, że ktoś postara się odpowiedzieć
W C++ nie da się zaimplementować “silnej typizacji” ponieważ jest coś takiego jak wskaźnik, do tego jest coś takiego jak wskaźnik na void(typ nieokreślony), istnieje rzutowanie wskaźników(można ze string* zrobić int* bez żadnego problemu).
Co do tablic: dzieje się tak, ponieważ kompilator “przerabia” odwołanie do elementu tablicy na coś takiego:
dynamic_cast nie zwróci null-a tylko wtedy jeśli obiekt jest danej klasy lub dziedziczy z tej klasy. Przykład:
class A{ virtual void TestowaFunkcja(){}};
class B : public A{};
class C : public B{};
class D : public C{};
class E : public D{};
D* Funkcja(A *obiekt)
{
return dynamic_cast(obiekt); //Jeśli obiekt jest klasy "d" nie zwróci null-a, jeśli jest innej - będzie null.
}
int main()
{
C obiekt;
D* wsk = Funkcja(&obiekt); //Będzie null;
D obiekt2;
wsk = Funkcja(&obiekt2); //Nie zwróci null-a.
E obiekt3;
wsk = Funkcja(&obiekt3); //Nie będzie null-a.
}
Aha, czyli w C++ pomimo kontroli statycznej można rzutować, ale kiedy była by to silna (słowo mówi samo za siebie) typizacja to takiego rzutowania nie można było by robić ? Dobrze rozumiem :?:
W “silnej typizacji” też można rzutować, jeśli rzutowanie jest dozwolone(np. jest operator rzutowania albo jest to proste rzutowania typu double -> int, int - > long(64-bit), int ->double).
Nie wiem czy wiesz o co mi chodzi. Wiem, że jeżeli byłby niżej to byłby to błąd, ale piszesz:
Więc wychodzi na to, że w językach gdzie istnieje “silna typizacja” nie ma wskaźników i czegoś takiego jak rzutowanie reinterpret_cast , które pracuje na wskaźnikach…
Aha już kapuję, nawet jeżeli nic by się tam nie zapisywało w to miejsce tak jak np. przy funkcji write na char* w ostream, gdzie potrzebny jest po prostu sam adres. I wobec tego w takich językach zastępują to np. szablonami jak podejrzewam. OK to dzięki za pomoc