Приведение типов у ссылок и указателей
int y=0;
double z=1.9;
y=z;
int* py;
double* pz;
//py=pz; error
//int& rp=z; error
Вопрос: почему можно присвоить переменной одного типа другую, а с указателями и ссылками так нельзя?
int y=0;
double z=1.9;
y=z;
int* py;
double* pz;
//py=pz; error
//int& rp=z; error
Вопрос: почему можно присвоить переменной одного типа другую, а с указателями и ссылками так нельзя?
Потому что при присвоении переменных происходит копирование значения с преобразованием к нужному типу (Например, 1.9 преобразуется в 1), в то время как при работе с указателями вы просто копируете адрес, и получается, что то, что лежит, например, по адресу в памяти double*
, представляет собой именно double
, а вы пытаетесь сказать "там не double
, там int
". А представления в памяти у них совершенно разные. Биты на одних и тех же местах имеют разный смысл. А еще и размеры могут не совпадать, и при присвоении (записи значения по адресу) вы запросто можете затирать чужую память.
Словом, это слишком опасная операция, чтобы разрешить ее просто так, неявно. А явно — вы можете сказать компилятору "я лучше знаю, что делаю!", типа
int * py = (int*)pz;
Только вот что из этого получится? См. пример такого преобразования https://ideone.com/mClrR1
Рассмотрим не встроенные типа, а классы для понятности. Классы
class A{};
class B{};
несовместимы. И присвоение друг другу не предусмотрено как по значению так и по указателю так и по ссылке.
А родственные классы уже могут взаимодействовать
class A{};
class B:public A{};
B b ;
B * bp = & b ;
B & bl = b ;
A a = b ;
A & al = bl ;
A * ap = bp ;
Так как в памяти объект типа B содержит часть объекта типа A. И компилятор может рассматривать только родственную часть.
Типы int
и double
не родственные и их указатели вы не сможете присваивать друг к другу. А значение можете, так как существует приведение одного типа к другому. В классах это выглядело бы так :
class A{};
class B{
public:
B(A const&){}
};