Как выделить массив в базовом конструкторе с размером на основе производного класса? - PullRequest
5 голосов
/ 27 марта 2009

У меня есть иерархия классов. Базовый класс использует некоторые параметры настройки, которые загружаются из файла (и могут быть загружены во время выполнения). Каждый производный класс может добавлять некоторые дополнительные параметры. Я ищу способ выделить массив параметров правильного размера в базовом конструкторе, чтобы мне не пришлось освобождать и перераспределять в производном классе. Я надеялся на что-то подобное, но это не работает (параметры всегда имеют 2 элемента):

   class Base
   { static int nParms;
     virtual int getNParms() { return nParms;}
     float *parameters;
   public:
     Base() 
     { parameters= new float[this->getNParms()];
       parameters[0] = globalReloadableX;
       parameters[1] = globalReloadableY;
     }
   };
   int Base::nParams =2;

   class Derived : public Base
   { static int nParms;
     virtual int getNParms() { return nParms;}
   public:
     Derived() : Base()
     { parameters[2] = globalReloadableZ;
     }
   }
   int Derived::nParams =3;

Я видел этот вопрос , но решение там не совсем работает для меня. Я также попытался сделать параметры регулярным массивом в каждом классе:

  class Base
  {  float parameters[2]
    ...
  class Derived : public Base
  {  float parameters[3]
    ...

но из-за этого у Derived есть 2 отдельных массива.

Есть идеи?

Ответы [ 6 ]

5 голосов
/ 27 марта 2009

Почему бы не передать требуемый размер массива в качестве параметра в конструктор базового класса?

(Причина, по которой виртуальная функция не вызывает производный класс, заключается в том, что именно так работают виртуальные функции C ++; концептуально до завершения конструктора производного класса тип объекта по-прежнему остается базовым классом.)

2 голосов
/ 28 марта 2009

Вы можете сделать это параметром для конструктора, как предлагали другие, но вы также можете сделать Base шаблоном класса с размером в качестве параметра. Это имеет много преимуществ, таких как устранение необходимости выделения массива в куче:

template <size_t nParams>
class Base
{
    float parameters[nParams];
public:
    Base()
    { // could use a static_assert(nParams > 1) here...
      parameters[0] = globalRelodableX;
      parameters[1] = globalRelodableY;
    }
};

class Derived : public Base<3>  // or whatever
{
public:
    Derived()
    { parameters[2] = globalRelodableZ; }
};
2 голосов
/ 27 марта 2009

Зачем использовать массив? Std :: vector позволит вам использовать столько параметров, сколько необходимо в производном классе, при этом основа не знает (или не заботится), сколько ему нужно.

2 голосов
/ 27 марта 2009

Как насчет того, чтобы сделать размер параметром?

class Base
{ static int nParms;
  virtual int getNParms() { return nParms;}
  float *parameters;
public:
  Base(int n = nParams) 
  { parameters= new float[n];
    parameters[0] = globalRelodableX;
    parameters[1] = globalRelodableY;
  }
};
int Base::nParams =2;

class Derived : public Base
{ static int nParms;
  virtual int getNParms() { return nParms;}
public:
  Derived() : Base(nParams)
  { parameters[2] = globalRelodableZ;
  }
}
int Derived::nParams =3;
0 голосов
/ 28 марта 2009

Мне нравятся ответы Уорвикера и Стива, в зависимости от того, что требуется. Если многие из этих объектов часто создаются и уничтожаются, вам нужен минимальный объем выделяемой памяти, и, следовательно, Earwicker превосходит их. Однако, если это что-то, что обычно «создается и редко переделывается», то я бы согласился с ответом Стива, поскольку с картами, как правило, гораздо проще работать, и они динамически растут по мере необходимости, но, вероятно, слишком много накладных расходов, если этот объект много чего делают и разрушают.

0 голосов
/ 28 марта 2009

Я хотел бы рассмотреть возможность использования std :: map. Он может расти вместе с базой и получаться независимо от количества параметров, используемых другими. Пары «ключ / значение», вероятно, проще управлять этими числовыми индексами, хотя это явно зависит от приложения.

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