Предоставить массив производных объектов для функции, которая работает с базовыми объектами - PullRequest
2 голосов
/ 11 августа 2011

Найти подходящее название для этого вопроса немного сложно для меня, но вот моя ситуация.Скажем, у меня есть базовый класс и производный класс, могу ли я передать функцию, которая принимает параметр типа * base, а не * производный

class base
{
protected:
    float M_OutputValue;
    float M_InputValue;
public:
    virtual void CalculateOutput() = 0;
        /* more functions */
};

class derived: public base
{
public:
    void CalculateOutput(){ /*stuff*/};
    /* more functions */
};

А вот функция, которая будет принимать базовый классв качестве ввода.


void CalculateAllOutputs(base* basearray, int NumberofElements)
{
    int temp = 0;
    while(temp &lt NumberOfElements)
    {
         basearray[temp]->CalculateOutput();
         temp++;
    }
};

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

Спасибо.

Ответы [ 2 ]

2 голосов
/ 11 августа 2011

Вы правы. Держитесь подальше от массивов и желательно используйте

std::vector<std::unique_ptr<base>>

или если у вас нет компилятора, готового к C ++ 0x (если это так, подумайте об обновлении), вы можете использовать

boost::ptr_vector<base>

Оба являются векторами указателей, которые автоматически очищают указанные объекты. Избегайте необработанных указателей, и, как вы заметили, простые массивы просто отстой.

Пример использования:

void calculate_outputs(const std::vector<std::unique_ptr<base>>& b)
{
    std::for_each(b.begin(), b.end(), [](const std::unique_ptr<base>& x)
    {
        x->CalculateOutput();
    });
}
2 голосов
/ 11 августа 2011

Ваше беспокойство совершенно верно.Передача массива производных не будет работать.Если вам нужен массив (или вектор) полиморфных объектов, вам нужно создать массив указателей.Это означает, что ваша функция будет выглядеть так:

void CalculateAllOutputs(base** basearray, int NumberofElements)
{
    int temp = 0;
    while(temp < NumberOfElements)
    {
         basearray[temp]->CalculateOutput();
         temp++;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...