2015-05-03 4 views
2

Я пытаюсь найти хороший способ хранения двух разных объектов класса в пределах одного вектора, каждый объект имеет свое собственное местоположение внутри вектора, поэтому объекты могут быть сохранены и доступны позже, когда это необходимо ,хранение двух разных объектов класса в векторе

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

Class A{ 
    public: 
    void changeNumber(int x) {number = x;} 
    private: 
    int number; 
}; 

Class B{ 
    public: 
    void changeNumber(int x) {number = x;} 
    private: 
    int number; 
}; 

struct Object{ 
    A a; 
    B b; 
}; 

Class Main{ 
    public: 
    void storeObject(Object ob) {object.push_back(ob);} 
    private: 
    std::vector<Object> objects; //when an object is passed both A and B objects are stored within the vector in the same location 
}; 

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

+0

Что именно вы пытаетесь достичь этим? То, что вы, вероятно, хотите иметь, - это общий базовый класс 'class A: Base {...', а затем сохранить указатели на 'Base' в' std :: vector объектов', но я мог бы не понимать, что происходит за конструкцией Object'. – mbschenkel

+0

Я пытаюсь сохранить два разных объекта класса, которые будут иметь разные функции и разные переменные, но я хочу сохранить оба объекта класса в одном векторе, чтобы мне было проще прокручивать размер вектора и выполнять задачи что необходимо сделать[email protected] – Jack

ответ

7

Если A и B имеют общие функции, и вы будете называть только эти элементы на элементах вектора, вы можете взять все общие члены и функции-члены и сделать из него базовый класс. Затем сделайте A и B производный класс Object:

class Object 
{ 
public: 
    virtual ~Object() = default; 

    void changeNumber(int x) { number = x; } 

private: 
    int number; 
}; 

class A : public Object 
{ 
    // extension of Object 
}; 

class B : public Object 
{ 
    // extension of Object 
}; 

В этом случае A ничем не отличается от B, так что все реализовано в Object.

Наконец, ваш вектор будет выглядеть следующим образом:

std::vector<Object*> objects; 

А вот более предпочтительное решение с std::shared_ptr, который освобождает память для вас после того, как элемент удаляется из вектора или разрушается иным образом.

std::vector<std::shared_ptr<Object>> objects; 

магазин объект:

void storeObject(std::shared_ptr<Object> const& ob) 
{ 
    objects.push_back(ob); 
} 

// Example calls 
Main main; 
main.storeObject(std::make_shared<Object>(A())); // store A 
main.storeObject(new A()); // logically same as above 

main.storeObject(std::make_shared<Object>(B())); // store B 
main.storeObject(new B()); 

boost::variant это путь при хранении нескольких различных типов, на которых вы не можете использовать наследование.

+0

Благодарим вас за ответ, поэтому, если классы A и B наследуются от класса Object, но у них также есть свои собственные функции, я был бы прав, говоря, что их невозможно хранить в одном векторе без использования 'boost: : variant'? @LogicStuff – Jack

+0

@Jack Я не знаю никого другого, кроме упомянутого здесь в ответах. Если вы хотите вызвать как 'objects [index] -> functionOfA()' и 'objects [index] -> functionOfB()', то нет. Но не забывайте, что некоторые виртуальные функции могут быть переопределены. Это может быть даже выполнимо с наследованием, и вы, возможно, не знаете. – LogicStuff

2

Вы можете использовать boost::variant. Это тип, который может представлять собой конечный набор типов, в вашем примере вы бы иметь

std::vector<boost::variant<A,B> > objects; 

Альтернативы (который на самом деле не соответствовать вашему USECASE, но может для будущих читателей) является boost::any. Он может представлять любой тип, который полезен, если во время компиляции у вас нет конечного списка возможных типов.

2

Если вы предпочитаете использовать свой собственный «variant эквивалент». Вы могли бы сделать что-то вдоль линий

struct Object{ 
    std::shared_ptr<A> a; 
    std::shared_ptr<B> b; 
}; 

std::vector<Object> objects; 

Object one; 
one.a = std::make_shared<A>(); 
objects.push_back(one); 

Object two; 
two.b = std::make_shared<B>(); 
objects.push_back(two); 

for(auto object: objects) { 
    if(object.a) { 
      object.a->changeNumber(1); 
    } else if(object.b) { 
      object.b->changeNumber(2); 
    } 
} 

Однако я до сих пор считаю, что решение это с соответствующей схемой наследования (как в the other answer) намного чище.

Смежные вопросы