@LevSvl08

Как в указатель на базовый класс вложить ссылку на класс наследник?

У меня есть 4 класса(4 фигуры), но в зависимости от входных данных, экземпляр создается только для одного класса.
Я хочу объявить, что будет объект класса заранее, до того, как обработаю входные данные( стороны а и b и угол x между ними). То есть в момент объявления я не знаю, какой конкретно класс будет реализовываться.
Поэтому я объявляю указатель на абстрактный класс Obj, чтобы потом когда станет ясно, какого класса будет создан экземпляр, присвоить этому адресу ссылку на сам экземпляр. Я знаю, что можно указатель на базовый класс может принимать ссылку на класс потомок, но как в этой конкретной ситуации передать ссылку, я не знаю

#include <string>
#include <iostream>
using namespace std;

class Obj 
{
    public:
        virtual void Introduce() = 0;
};

class Romb : Obj
{
    public:
        void Introduce() override
        {
            cout << " Это ромб!\n";
        }
};
class Kvadrat : Obj
{
public:
    void Introduce() override
    {
        cout << " Это квадрат!\n";
    }
};

class Prmugolnik : Obj
{
public:
    void Introduce() override
    {
        cout << " Это прямоугольник!\n";
    }
};

class Parallelogram : Obj
{
public:
    void Introduce() override
    {
        cout << " Это параллелограмм!\n";
    }
};




int main()
{
    short a, b;
    float x;
    Obj *object;


    cout << " Сторона A = ";
    cin >> a;

    cout << " Сторона B = ";
    cin >> b;

    cout << " Угол X = ";
    cin >> x;

    if (x == 90)
    {
        if (a == b)
        {
            Kvadrat kv;
            object = kv;
        }
        else
        {
            Prmugolnik prgl;
        }
    }
    else
    {
        if (a == b) 
        {
            Romb rmb;
        }
        else 
        {
            Parallelogram prlgm;
        }
    }

}
  • Вопрос задан
  • 310 просмотров
Решения вопроса 1
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
Правильно - вот так:
object = new Kvadrat();

Теоретически, можно было бы делать как вы пытаетесь:
object = &kv;

Но конкретно в вашем коде - это будет UB, потому что kv - это локальная переменная и у нее очень огранниченная область видимости - внутри if. И вот за пределеами этого if, где вы и попытаетесь, очевидно, использовать указатель object, эта локальная переменная будет уже уничтожена. У вас будет т.н. висячий указатель - указывающий туда, где данные были, а сейчас там может быть все, что угодно.

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

Но лучше, все-таки, не плодить лишних сущностей и создавать объект сразу в куче с помощью new. Тогда он сам нигде не уничтожится.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы