Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I access objects from a vector of "pointer-to-objects" in c++

I'm writing a program that creates a vector of pointer-to-objects.

How do I access the individual objects that the pointers reference from the pointer-to-objects vector?

I'm trying to call the speak() function in the class Object for each of the objects that the pointers inside the vector reference.

Thank you for your time

class Object
{
public:
    void speak()
    {
        cout<<"Hello!"<<endl;
    }
};

int main()
{
    int choice;

    vector<Obj*> objVector; //create empty vector of "pointer-to-object"
    Object* ptrObj; //point to object

    while (choice!=5)
    {
        cout <<"1.Create Object\n";
        cout <<"2.Destroy Object\n";
        cout <<"3.Print number of existing Objects\n";
        cout <<"4.Tell existing Objects to say Hello\n";
        cout <<"5.Quit Program"<<endl;
        cout <<"Please enter your choice: ";
        cin >> choice;

    if (choice==5)
        cout <<"\nProgram is quitting\n"<<endl;
    else if (choice==1)
    {
        ptrObj= new Object;
        ObjVector.push_back(ptrObj); //adding an Object object
    }
    else if (choice==2)  //remove object
    {
        objVector.pop_back();
    }
    else if (choice==3)
    {
        cout <<"\nThere are " << objVector.size() <<" objects total.\n" << endl;
    }
    else if (choice==4)
    {
        for (int i=0; i<objVector.size(); i++)
        {
           ????????????
        }
    }
    }
    return 0;
}
like image 448
xai Avatar asked Oct 24 '25 12:10

xai


1 Answers

In your existing code, you can access the pointer exactly the way you use it elsewhere in code:

Object* obj = objVector[i];
obj->speak();
// or, simply:
objVector[i]->speak();

Using the operator -> is simply another way to say (*objVector[i]).speak().

Alternatively, the idiomatic approach to writing the loop would look like this:

for(vector<Object*>::iterator it = objVector.begin(); it != objVector.end(); ++it) {
    // iterators work like another level of pointers, and need to be dereferenced:
    (*it)->speak();
}

If your compiler supports C++11, you can rewrite the loop like this:

for(auto it = std::begin(objVector); it != std::end(objVector); ++it) {
    (*it)->speak();
}

Or like this, using range-based for, which dereferences the iterator for you:

for(auto& obj : objVector) {
    obj->speak();
}

As an aside, there are cases where you will not be sure whether objVector[i] is even in the vector at all, and accessing it may crash your program or even cause demons to fly forth from your nasal cavity.

For added safety, you can reference positions in your vector with the at function, like so:

try {
    for (int i=0; i<objVector.size(); i++)
    {
        Object* obj = objVector.at(i);
        obj->speak();
    }
} catch (const std::out_of_range& ex) {
    cerr << "no object at position " << i << " in objVector" << endl;
    cerr << "objVector says " << ex.what() << endl;
}

Notice, though, that this is a lot slower, although it gives you a chance to handle the problem in the catch block. The try block will run the loop and stop and run the catch block if the at function throws an exception - which will be an exception of type out_of_range. Note also that using [i] will not do the same thing, because it does not throw an exception - it doesn't even bother to check if i is within the length of the vector. This happens to also be why [i] is faster than .at(i).

Finally, also notice that the loops using iterators cannot encounter this particular problem, so long as you don't try to use the iterators after adding or removing something from the vector.

like image 183
greyfade Avatar answered Oct 26 '25 01:10

greyfade



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!