Ошибка при вызове функции и передаче ссылки на указатель с производным типом

Может кто-нибудь объяснить, почему следующий код недействителен? Это потому, что смещение для переменной с именем d отличается от смещения переменной с именем b?

class Base { public: int foo; };

class Derived : public Base { public: int bar; };

int DoSomething( Base*& b ) { return b->foo; }

Base* b = new Derived;
Derived* d = new Derived;

int main()
{
   DoSomething( d );
}

Это ошибка, которую выдает онлайн-компилятор C ++ Comeau:

"ComeauTest.c", line 12: error: a reference of type "Base *&" (not const-qualified)
          cannot be initialized with a value of type "Derived *"
     DoSomething( d );
                  ^

Это похожий вопрос, но отличается, потому что в моем примере я объявляю d как тип указателя: Передача ссылок на указатели в C ++

Обратите внимание, что это компилируется, когда я передаю b в DoSomething.


person Jared    schedule 04.09.2009    source источник


Ответы (3)


Представьте, что вы могли бы это сделать. Ссылка не является константой, поэтому DoSomething может назначить указателю, и это будет видно в вызывающей стороне. В частности, внутри DoSomething мы можем изменить указатель, чтобы он указывал на что-то, что не является экземпляром Derived. Если после того, как мы вернемся, вызывающий объект попытается сделать с указателем что-то, специфичное для производного объекта, он взорвется.

person moonshadow    schedule 04.09.2009

Это не имеет никакого отношения к зачетам. Обратите внимание, что Derived в вашем примере имеет поля foo и bar (и да, у них будут разные смещения, но здесь это не имеет значения).

Если бы это было разрешено, это было бы небезопасно. Рассмотрим этот код:

class Base { public: int foo; };

class Derived1 : public Base { public: int bar; };

class Derived2 : public Base { public: float baz; };

void DoSomething(Base*& b) { b = new Derived2; }

Derived1* d = new Derived1;
DoSomething(d); // d is of type Derived1*, but now points to object
                // of incompatible type Derived2
person Pavel Minaev    schedule 04.09.2009

Предположим, что DoSomething был определен следующим образом:

int DoSomething( Base*& b ) { b = new Base; }

К сожалению, теперь, когда main вызывает DoSomething, d указывает на Base, а не на Derived.

person Omnifarious    schedule 04.09.2009