Указатель базового класса может указывать на объект производного класса. Почему наоборот не так? - PullRequest
65 голосов
/ 08 февраля 2011

Указатель базового класса может указывать на объект производного класса.Почему наоборот не верно без кастинга?Логически базовый класс не будет иметь достаточной информации о производном классе, но производный класс также должен иметь информацию о базовом классе.Я скучаю по некоторым основам здесь.

Ответы [ 11 ]

130 голосов
/ 08 февраля 2011

Если я скажу, что у меня есть собака, вы можете смело предполагать, что у меня есть домашнее животное.

Если я скажу вам, что у меня есть домашнее животное, вы не знаете, является ли это животное собакой, это может быть кошка или даже жираф. Не зная дополнительной информации, вы не можете с уверенностью предположить, что у меня есть собака.

аналогично, производный объект является объектом базового класса (так как это подкласс), поэтому на него можно указывать указателем базового класса. Однако объект базового класса не является объектом производного класса, поэтому его нельзя назначить указателю производного класса.

(Скрип, который вы сейчас услышите, - это растяжение аналогии)

Предположим, вы хотите купить мне подарок для моего питомца.

В первом сценарии вы знаете, что это собака, вы можете купить мне поводок, все счастливы.

Во втором сценарии я не сказал вам, что такое мой питомец, поэтому, если вы все равно собираетесь купить мне подарок, вам нужно знать информацию, которую я вам не сказал (или просто догадаться), вы покупаете мне поводок Если окажется, что у меня действительно есть собака, все счастливы.

Однако, если у меня действительно был кот, то теперь мы знаем, что вы сделали неверное предположение (приведение) и у вас несчастный кот на поводке (ошибка времени выполнения).

ClassCastException Cat

11 голосов
/ 08 февраля 2011

У нас есть два объекта.

class A {
   int a;
};

class B : A {
   int b;
};

Выделите экземпляр B. Мы можем взаимодействовать с этим как A* или B*.

Выделите экземпляр A. Если мы приведем его к B*, должно ли быть выделено место для члена b?

9 голосов
/ 08 февраля 2011

Э-э, потому что базовый класс не является производным классом.

Если у вас есть действительный указатель на тип, то вы говорите, что указанный объект будет иметь определенные данные в определенных местах, чтобы мы могли их найти. Если у вас есть указатель на производный объект, то вы гарантируете, что указанный объект содержит все элементы данных Derived, но когда вы указываете на Base, он не имеет этого и Bad Things Happen ™. 1003 *

Однако в Derived гарантированно все элементы базы данных будут находиться в одинаковых местах. Вот почему указатель на Base может указывать на Derived.

4 голосов
/ 08 февраля 2011

Потому что производный класс включает в себя все, что находится в базовом классе.Но базовый класс не включает в себя все, что находится в производном классе.

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

3 голосов
/ 08 февраля 2011

Это действительно, потому что тигр - это животное:

    Animal * pAnimal = new Tiger();

Это недопустимо, потому что это неправда, что объект - отравленная лягушка дротиков.

    PoisonDartFrog * pPoisonDartFrog = new GenericFrog();
1 голос
/ 26 августа 2018

Краткий ответ

class A{
    public: 
        method1();
};

class B: public A{
    public: 
        method2();
};


int main(){

// Case 1
A* ptr_base = new B();
// Here I can call all the methods in A by ptr_base even though it is assigned B ...
// ... because B is derived from A and has all the information about methods of A
// Case 2
B* ptr_derived = new A(); // this will cause error
// Now here ptr_derived is assigned information of A ...
// ... So with this information can I call (*ptr_derived).method2(); ?...
// ... the answer is No because A does not have information of method2() ...;
// ... thus this declaration loses its meaning and hence error.
return 0;
}
1 голос
/ 12 декабря 2013
class Base
{
public:
    int a;
}

class Derived : public Base
{
public:
    float b;
}

Base * pBase = new Base();
pBase->a = 7; // setting the value of a in the base

// make a pDerived that points to the SAME DATA as pBase
Derived * pDerived = pBase;
pDerived->a = 5; // this would be okay, base has a public member 'a'
pDerived->b = 0.2f; // error pBase has no data member b and pDerived
                    // points to the SAME DATA as pBase
1 голос
/ 08 февраля 2011

Поскольку C ++ является статически типизированным языком, и разрешение неявных преобразований из базы в производные может нарушить систему типов.Бьярне Страуструп не хотел ошибок "сообщение не понято" во время выполнения.

0 голосов
/ 10 ноября 2018

Как правило, указатель одного типа не может указывать на объект другого типа. Однако есть важное исключение из этого правила, которое касается только производных классов. В этой ситуации указатель типа BASE * может указывать на объект типа Derived, то есть указатель базового класса может указывать на объект производного класса, но, наоборот, неверен, поскольку базовый объект не является объектом подкласса.

0 голосов
/ 08 февраля 2011

Если назначить адрес из указателя базового класса в указатель производного класса, вы можете потенциально назначить объект базового класса указателю производного класса.Вы рискуете получить доступ к производным членам класса, когда у вас нет производного класса.В то время как методы производного класса будут работать с базовым классом, они будут делать это только в том случае, если метод не получит доступ к данным члена производного класса.

Это огромный риск.

Поэтому мы заставляем вассоставьте так, чтобы вам пришлось признать заявление об отказе от ответственности (вы можете сделать глупую ошибку, пожалуйста, будьте осторожны).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...