Приведение типов у ссылок и указателей

Рейтинг: -1Ответов: 2Опубликовано: 05.04.2023
int y=0;
double z=1.9;
y=z;

int* py;
double* pz;
//py=pz; error
//int& rp=z; error

Вопрос: почему можно присвоить переменной одного типа другую, а с указателями и ссылками так нельзя?

Ответы

▲ 5Принят

Потому что при присвоении переменных происходит копирование значения с преобразованием к нужному типу (Например, 1.9 преобразуется в 1), в то время как при работе с указателями вы просто копируете адрес, и получается, что то, что лежит, например, по адресу в памяти double*, представляет собой именно double, а вы пытаетесь сказать "там не double, там int". А представления в памяти у них совершенно разные. Биты на одних и тех же местах имеют разный смысл. А еще и размеры могут не совпадать, и при присвоении (записи значения по адресу) вы запросто можете затирать чужую память.

Словом, это слишком опасная операция, чтобы разрешить ее просто так, неявно. А явно — вы можете сказать компилятору "я лучше знаю, что делаю!", типа

int * py = (int*)pz;

Только вот что из этого получится? См. пример такого преобразования https://ideone.com/mClrR1

▲ 2

Рассмотрим не встроенные типа, а классы для понятности. Классы

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&){}
};