Создание массива объектов, содержащих ссылки - PullRequest
0 голосов
/ 29 февраля 2012

Каков наилучший способ справиться со следующей ситуацией?

Предположим, у меня есть что-то, что должно вести себя так:

class Foo
    {
    public:
         Foo(Bar& bar):m_bar(bar){}
    private:
         Bar& m_bar;
    };

Foo: s должен иметь действительную ссылку на Bar: s.Также разным Foo: s нужны разные или одинаковые Bar: s.

Я хочу хранить Foo: s в массиве.Однако, поскольку Foo потребует конструктор не по умолчанию, он не будет работать.

Я мог бы создать массив указателей на Foo: s, но затем мне нужно вызвать new и удалить для каждого объекта в этом массиве.

Я мог бы определить Foo следующим образом:

class Foo
    {
    public:
         void init(Bar& bar)
             {
             m_bar=&bar;
             }
    private:
         Bar* m_bar;
    };

, но тогда можно создать неинициализированный Foo: s.

Как насчет размещения нового типа?

Ответы [ 3 ]

0 голосов
/ 29 февраля 2012

Во-первых, извините за мой первый ответ, я неправильно понял вопрос.Надеюсь, вот лучшее решение: вы можете создать vector элементов без конструктора по умолчанию, например:

#include <iostream>
#include <vector>

using namespace std;


class Foo 
{ 
public: 
    Foo(int& bar): m_pBar(bar)
    { } 

    Foo& operator=(const Foo& other)
    { m_pBar = other.m_pBar;  }

    int Get()
    { return m_pBar; }

private: 
    int& m_pBar; 
}; 


int main(int argc, char** argv)
{
    int test[10]  = { 0 };

    vector<Foo> vect;
    for (int& i: test)
        vect.emplace_back(i);

    test[0] = 1;
    cout << vect[0].Get() << endl;

    return 0;
}
0 голосов
/ 01 марта 2012

Наконец я реализовал пользовательский контейнер со следующим конструктором:

template<class T>
template<class U,class V>
Array<T>::Array(unsigned int n,U source_iterator,const V& source_resource):memory(n*sizeof(T))
    {
    data=(T*)memory.pointerGet();
    unsigned int k;
    try
        {
        for(k=0;k<n;k++)
            {
            new(data+k)T(*source_iterator,source_resource);
            ++source_iterator;
            }
        }
    catch(...)
        {
        while(k>0)
             {
             k--;
             data[k].~T();
             }
        throw;
        }
    length=n;
    capacity=n;
}
0 голосов
/ 29 февраля 2012

Вы все еще можете использовать указатели, но вместо использования необработанных указателей используйте unique_ptrs. Они доступны в c ++ 11, но если вы используете более старый компилятор, вы можете использовать реализацию boost.

Например

class Foo
{
public:
  Foo(unique_ptr<Bar> bar):m_pBar(bar){}
private:
  unique_ptr<Bar> m_pBar;
};

Таким образом, вам не нужно беспокоиться о вызове delete для объектов Bar, поскольку они удаляются, когда на них больше нет ссылок.

Тогда вы можете использовать Foo вот так

unique_ptr<Bar> pBar(new Bar());
Foo(pBar);

EDIT: изменено использование unique_ptr вместо shared_ptr и добавлен пример использования

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