C ++ понижение родительского указателя на дочерний указатель, используемый в качестве параметра функции - PullRequest
0 голосов
/ 02 июля 2018

Я хочу использовать дочерний указатель вместо родительского параметра в некоторой функции. Вот упрощенный код

#include <iostream>
#include <string>
using namespace std;
class Parent
{
    private:
        string value;
    public:
        void SetValue(const string& in){ value = in; }
        const string& GetValue() const { return value; }
        virtual ~Parent() {};
};
class Child : public Parent
{
};
void Func(Parent* obj)
{
    Child* cobj = dynamic_cast<Child*>(obj);
    cobj->SetValue("new value");
    delete cobj;
}
int main(int argc, char** argv)
{
    Child* cobj = new Child();
    Func(cobj);
    cout<<"value: "<<cobj->GetValue();
    return 0;
}

Но возвращается value:
Func не устанавливает свойство value. Как я могу исправить код?
Update1:
Но с этим кодом:

#include <iostream>
#include <string>
using namespace std;
class Parent
{
    private:
        string value;
    public:
        void SetValue(const string& in){ value = in; }
        const string& GetValue() const { return value; }
        virtual ~Parent() {};
};
class Child : public Parent
{
    private:
        int number;
    public:
        void SetNumber(int in){ number = in; }
        int GetNumber() const { return number; }
};
void Func(Parent* obj)
{
    Child* cobj = dynamic_cast<Child*>(obj);
    cobj->SetValue("new value");
    cobj->SetNumber(100);
    delete cobj;
}
int main(int argc, char** argv)
{
    Child* cobj = new Child();
    Func(cobj);
    cout<<"value: "<<cobj->GetValue()<<endl;
    cout<<"number: "<<cobj->GetNumber()<<endl;
    return 0;
}

Я получаю value: number: 100
Почему SetNumber работает, а SetValue - нет?

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

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

Вы можете исправить код, удалив строку delete cobj;. Однако вам также следует проверить, что результат dynamic_cast не равен нулю, прежде чем его разыменовывать.

Если неясно, выражение delete удаляет объект, на который указывает. Не существует такого понятия, как «удалить указатель».

0 голосов
/ 02 июля 2018

Ваша проблема не имеет ничего общего с наследованием или параметрами функции. Проблемный код может быть уменьшен до:

Child* cobj = new Child();
cobj->SetValue("new value");
delete cobj;
cobj->GetValue();

Последние две строки - это проблема. delete cobj уничтожает объект, но cobj->GetValue() все еще пытается использовать его. Этот код имеет неопределенное поведение.

Чтобы исправить код, вам нужно удалить либо delete cobj, либо GetValue() вызов. В любом случае, не пытайтесь использовать объект после того, как он был уничтожен.

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