Могу ли я объявить переменную-заполнитель в родительском классе и объявить ее в разных типах в дочерних классах?

Могу ли я как-то объявить masiv в родительском классе, чтобы деструктор мог работать правильно, или мне нужно в основном копировать-вставлять код для каждого дочернего класса?

class Parent{
public:
    int X;
    int Y;
    // I want to declare a placeholder "masiv" here.

    ~Parent()
    {
        for(int i = 0; i < Y; i++)
            delete [] masiv[i];
        delete [] masiv;
    }
};

class Child1 : public Parent {
public:
    int* *masiv;
    // Create method
};

class Child2 : public Parent {
public:
    float* *masiv;
    // Create method
};

Примечание. Дочерние классы используют другие методы, которые идентичны, но для простоты я не добавлял их в код. Однако я хотел бы добавить их и к родителю, но не могу, так как там не объявлено «masiv».

Обновлено: Шаблоны творили чудеса! Обратите внимание, что я все еще новичок в программировании и до сих пор не знал об их существовании (и о том, как их использовать).

Я думаю, вам придется сделать класс Parent шаблоном. https://en.cppreference.com/w/cpp/language/class_template

drescherjm 11.12.2020 14:27

Как насчет использования std::vector<int> и std::vector<float> в дочерних классах и удаления родительского деструктора?

PiotrNycz 11.12.2020 15:47
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
171
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Это может быть легко достигнуто с помощью шаблона

template<typename T>
class Parent{
public:
    int X;
    int Y;
    // I want to declare a placeholder "masiv" here.
    T** masiv;

virtual ~Parent()  // not an option the virtual destructor
{
    for(int i = 0; i < Y; i++)
      delete [] masiv[i];
    }
    delete [] masiv;
};

class Child : public Parent<int>
{
   // you already have int* masiv here;
}

ОДНАКО то, как написан фрагмент, и причина, по которой вы хотите объявить в родительском классе, в основном является плохим дизайном, и вы рассматриваете его как XY-проблему,

стоит отметить, что это отличается от кода OP, потому что если один класс наследуется от Parent<int>, а другой от Parent<float>, то они не имеют общего базового класса.

463035818_is_not_a_number 11.12.2020 14:30

«ОДНАКО, как написан фрагмент, и причина, по которой вы хотите объявить в родительском классе, в основном является плохим дизайном, и вы рассматриваете это как проблему XY». Как так? Тут много утверждений.

Asteroids With Wings 11.12.2020 14:36

Это сработало! Мой дизайн получился таким, потому что я начал писать версию для своего класса, используя int, и другую версию для своего класса, используя float. Затем я решил создать родительский класс, в котором будут сохранены все сходства двух классов, чтобы уменьшить длину кода. X и Y — это просто переменные, которые использовались в моих дочерних классах, поэтому я передал их родительскому.

WereElf 11.12.2020 14:48

«Правильно» сделать, чтобы Child1 и Child2 имели деструкторы, которые очищают ресурсы, принадлежащие этим классам и указанные ими. В этом случае да, это означает, что у вас будут идентичные delete[] masiv линии (и другие), хотя это не большая проблема.

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

В качестве альтернативы у вас может быть шаблон промежуточного базового класса, который владеет (и управляет) T** masiv и является производным от Parent; тогда Child1 будет производным от YourBase<int>, а Child2 будет производным от YourBase<float> с использованием любопытно повторяющегося шаблона шаблона. Однако это слишком много для очень конкретного простого примера, который вы показали.

class Parent
{
public:
    int X;
    int Y;
    
    // Consider a virtual destructor here; depends what you're doing
};

template <typename T>
class MasivManager : public Parent
{
public:
    T** masiv;
    
    ~MasivManager()
    {
        for (std::size_t i = 0; i < Y; i++)
            delete[] masiv[i];
        delete[] masiv;
    }
};

class Child1 : public MasivManager<int> {};
class Child2 : public MasivManager<float> {};

Вы можете передать эту работу самой Parent, сделав ее шаблоном:

template <typename T>
class Parent
{
public:
    int X;
    int Y;
    T** masiv;
    
    // Consider making this a virtual destructor; depends what you're doing
    ~Parent()
    {
        for (std::size_t i = 0; i < Y; i++)
            delete[] masiv[i];
        delete[] masiv;
    }
};

class Child1 : public Parent<int> {};
class Child2 : public Parent<float> {};

Однако то, «имеет ли это смысл», зависит от его семантики в вашем приложении, а мы этого не видим. Логично ли, что Parent владеет masiv? Будут ли все виды Parent делать это? (Основываясь на том, где живут X и Y, я думаю «да», но решать только вам.)

Вы также потеряете общий базовый класс (поскольку специализации шаблонов — это разные типы), хотя вас это может волновать, а может и не волновать.

Дело в том, что я даю упрощенную версию своего кода. Мои дочерние классы разделяют не только метод деструктора, но большинство методов выглядят одинаково, и большинство из них используют этот «masiv».

WereElf 11.12.2020 14:34

@WereElf Вы ничего не сказали об этом в своем вопросе. :( Тем не менее, я остаюсь при своем ответе: я думаю, что описал все шаблоны, которые я бы рассмотрел в этом сценарии.

Asteroids With Wings 11.12.2020 14:35

Другие вопросы по теме