Вопрос

Просто интересно, из-за проблемы, с которой я столкнулся, можно ли создать вектор указателей?И если да, то как?В частности, относительно использования итераторов и .begin() с ним, т.е.:Как бы я превратил этот вектор в вектор указателей:

class c
{
     void virtual func();
};

class sc:public c
{
     void func(){cout<<"using func";}
};

sc cobj;

vector<c>cvect
cvect.push_back(cobj);
vector<c>::iterator citer

for(citer=cvect.begin();citer<cvect.end();citer++)
{
     citer->func();
}
Это было полезно?

Решение 2

vector <c> cvect не является вектором указателей. Это вектор объектов типа c. Вы хотите vector <c*> cvect. и вы, вероятно, хотите:

cvect.push_back( new c );

А затем, учитывая итератор, вы хотите что-то вроде:

(*it)->func();

Конечно, вполне вероятно, что вам вообще не нужен вектор указателей ...

Другие советы

Конечно.

vector<c*> cvect;
cvect.push_back(new sc);
vector<c*>::iterator citer;
for(citer=cvect.begin(); citer != cvect.end(); citer++) {
  (*citer)->func();
}

Что следует иметь в виду:

Вам нужно будет выполнить очистку после себя, если вы используете динамически выделяемую память, как я это сделал в своем примере.

например.:

 for(...) { delete *i; }

Это можно упростить, используя вектор shared_ptrс (как boost::shared_ptr).Не пытайтесь использовать std::auto_ptr для этого он не будет работать (даже не скомпилируется).

Еще одна вещь, о которой следует помнить: вам следует избегать использования < чтобы сравнивать итераторы в вашем цикле, когда это возможно, это будет работать только для итераторов, которые моделируют итератор произвольного доступа, что означает, что вы не можете изменить свой код для использования, например.а std::list.

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

class c
{
     void virtual func();
};

class sc:public c
{
     void func(){cout<<"using func";}
};

sc cobj;

vector<c*> cvect;             // Note the type is "c*"
cvect.push_back(&cobj);       // Note the "&"
vector<c*>::iterator citer;

for(citer=cvect.begin();citer != cvect.end();citer++)   // Use "!=" not "<"
{
     (*citer)->func();
}

Обратите внимание, что с вектором указателей, вам необходимо самостоятельно управлять памятью , поэтому будьте очень осторожны - если вы будете использовать локальные объекты (как указано выше), они не должны выпадать области видимости до контейнера. Если вы используете указатели на объекты, созданные с помощью new, вам нужно delete вручную их удалить, прежде чем контейнер будет уничтожен. В этом случае вам обязательно следует использовать интеллектуальные указатели, например smart_ptr, предоставленные Boost .

Да, конечно.

// TestCPP.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <vector>


using namespace std;

class c
{
public:
    void virtual func() = 0;
};

class sc:public c
{
public:
    void func(){cout<<"using func";}
};

int _tmain(int argc, _TCHAR* argv[])
{
    sc cobj;

    vector<c*> cvect;
    cvect.push_back(&cobj);
    vector<c*>::iterator citer;

    for(citer=cvect.begin();citer<cvect.end();citer++)
    {
        (*citer)->func();
    }

    return 0;
}

Обратите внимание на объявление vector<c*> cvect и использование cvect.push_back(&cobj).

Из предоставленного кода вы неправильно используете итератор. Чтобы получить доступ к члену, на который указывает итератор, вы должны использовать *citer вместо citer.

Вы создали vector<c*> для вектора указателей. Затем используйте new для выделения памяти для объектов c и вставьте их в вектор. Кроме того, не забывайте, что вы должны delete себя и vector.clear () не освободит память, выделенную для объектов c. Здесь вы должны хранить c как вектор указателей, иначе вызов виртуальной функции не будет работать.

Попробуйте библиотеку контейнеров для повышения указателей , Он имеет несколько преимуществ перед обычным вектором указателей, например:

my_container.push_back( 0 );            // throws bad_ptr 
ptr_vector<X> pvec; 
std::vector<X*> vec;
( *vec.begin() )->foo(); // call X::foo(), a bit clumsy
pvec.begin()->foo();     // no indirection needed
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top