унылая проблема в с ++ - PullRequest
       4

унылая проблема в с ++

0 голосов
/ 15 ноября 2010
#include <iostream>
using std::cout;
using std::endl;
class Base
{
public :
    void f();
    void g();

    int mBaseData1;

};

class Derived : public Base
{
public : 


    int mDerivedData1;
};

void main()
{

    Base* base = new Base();
    Derived* derived = (Derived*)(base); // DownCast
    derived->mDerivedData1 = 6;
    cout<< derived->mDerivedData1<<endl; // Result = 6;
}

в этом коде new base() выделение памяти в куче

и Derived* derived = (Derived*)(base) база приведения к производной

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

Ответы [ 5 ]

8 голосов
/ 15 ноября 2010

Причина, по которой вы не можете найти место для памяти mDerivedData1, заключается в том, что память не была выделена .Вы выполнили неверное приведение типа .Вещество, хранящееся в base, является указателем на экземпляр Base.Использование приведения типа, чтобы сказать компилятору, что это на самом деле указатель на экземпляр Derived, этого не делает (но в любом случае компилятор вам поверит, потому что вы один).Объект все еще просто Base.Если вы хотите Derived, то вам нужно создать экземпляр Derived.Вы можете использовать dynamic_cast для преобразования указателя Base в указатель Derived.

Base* base = new Derived;
Derived* derived = dynamic_cast<Derived*>(base);
derived->mDerivedData1 = 6;
4 голосов
/ 15 ноября 2010

Будет работать правильно, если вы измените:

Base* base = new Base();

до:

Base* base = new Derived();

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

2 голосов
/ 15 ноября 2010

Ваша программа демонстрирует неопределенное поведение.Вы не можете получить доступ к mDerivedData1, потому что у вас нет экземпляра Derived.

2 голосов
/ 15 ноября 2010

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

C ++ позволяет вам делать то, что вы говорите, по большей части. Вы стреляете себе в ногу. :)

1 голос
/ 15 ноября 2010

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

Редактировать:

Если вы не понимаете, как работает кастинг:

Объект никогда не меняется во время каста - на самом деле объект на самом деле просто смежныйблок памяти.Когда объект преобразуется, изменяется только то, как программа видит , а работает с объектом.

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

В общем, если B наследуется от A:

  1. Вы можете привести экземпляр B к A
  2. Вы можете привести экземпляр B, который ужеприведите A назад к B, но это может указывать на небрежную архитектуру вашей программы.
  3. Вы не можете ( должен не) приводить экземпляр A к B, так как это приведет к неопределенному поведению.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...