Задать вопрос
@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;
        }
    }

}
  • Вопрос задан
  • 452 просмотра
Подписаться 1 Простой 4 комментария
Помогут разобраться в теме Все курсы
  • Нетология
    Разработчик на C++: Профессия + специализация + нейросети
    12 месяцев
    Далее
  • Skillbox
    Разработчик на C++
    7 месяцев
    Далее
  • Яндекс Практикум
    Разработчик C++
    9 месяцев
    Далее
Решения вопроса 1
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
Правильно - вот так:
object = new Kvadrat();

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

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

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

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

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

Похожие вопросы
ITK academy Казань
от 75 000 до 130 000 ₽
ITK academy Нижний Новгород
от 75 000 до 120 000 ₽
Data World Москва
от 180 000 до 210 000 ₽