Могу ли я как-то объявить 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».
Обновлено: Шаблоны творили чудеса! Обратите внимание, что я все еще новичок в программировании и до сих пор не знал об их существовании (и о том, как их использовать).
Как насчет использования std::vector<int> и std::vector<float> в дочерних классах и удаления родительского деструктора?
Это может быть легко достигнуто с помощью шаблона
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>
, то они не имеют общего базового класса.
«ОДНАКО, как написан фрагмент, и причина, по которой вы хотите объявить в родительском классе, в основном является плохим дизайном, и вы рассматриваете это как проблему XY». Как так? Тут много утверждений.
Это сработало! Мой дизайн получился таким, потому что я начал писать версию для своего класса, используя int, и другую версию для своего класса, используя float. Затем я решил создать родительский класс, в котором будут сохранены все сходства двух классов, чтобы уменьшить длину кода. X и Y — это просто переменные, которые использовались в моих дочерних классах, поэтому я передал их родительскому.
«Правильно» сделать, чтобы 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 Вы ничего не сказали об этом в своем вопросе. :( Тем не менее, я остаюсь при своем ответе: я думаю, что описал все шаблоны, которые я бы рассмотрел в этом сценарии.
Я думаю, вам придется сделать класс Parent шаблоном. https://en.cppreference.com/w/cpp/language/class_template