Подтвердить что ты не робот

Указатель базового класса может указывать на объект производного класса. Почему наоборот?

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

ClassCastException Cat

Ответ 2

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

class A {
   int a;
};

class B : A {
   int b;
};

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

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

Ответ 3

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

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

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

Ответ 4

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

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

Ответ 5

Это верно, потому что тигр - это животное:

    Animal * pAnimal = new Tiger();

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

    PoisonDartFrog * pPoisonDartFrog = new GenericFrog();

Ответ 6

Поскольку С++ является статически типизированным языком и позволяет неявные преобразования Base-to-Derived разбивает систему типов. Bjarne Stroustrup не хотел, чтобы ошибки "времени не поняли".

Ответ 7

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

Ответ 8

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

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;
}

Ответ 9

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

struct Base {};
struct Derived : Base {};
struct Derived2 : Base {};
Base* p = new Derived(); //Fine, Derived inherits from Base
Derived* d = new Base(); //Not fine, Base is not an instance of nor derived from Derived.
Derived* d2 = new Derived2(); // Also not fine, Derived2 derives from Base, but is not related to Derived.

Что касается причин: Обычно базовый указатель более общий, чем производный указатель. Как таковой, он знает меньше о унаследованном типе. Производный указатель не может быть назначен указатель на базовый тип без кастинга просто потому, что он не может определить, имеет ли базовый указатель тип Derived или один из его дочерних элементов.

Ответ 10

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

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

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

Ответ 11

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

Ответ 12

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

  1. Если у нас есть указатель базового типа (* B):

затем мы ожидаем объект базового типа (и хотели бы получить доступ к его функциям) по адресу, указанному буквой B, и если мы получим объект производного типа по этому адресу, то мы также сможем получить доступ к требуемым функциям. Это потому, что производный тип - это базовый тип.

  1. Если мы получили указатель производного типа (* D):

тогда мы ожидаем объект производного типа по адресу, указанному буквой D, и если мы получим там объект базового типа, мы не сможем получить доступ к информации производного класса из объекта базового типа, поскольку базовый тип не является производным типом.