简体   繁体   中英

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;
}

The easiest way is to use *(objVector[i])

To access speak, objVector[i]->speak is just shorter.

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.

You can dereference them with *. Like *(ObjVector[i]) But if you just need to call a method of object you can do it with -> ObjVector[i]->speak()

Unrelated to the question, but I drop some comment to revise the program.

As others pointed out, you can call object function from pointer contained on vector with doing objVector[i]->speak() .

However, as @greyfade pointed out, there is leaking memory issue. You have to delete object when the object is created by new . You can delete object by delete like this,

Object* ptr = objVector.back();
objVector.pop_back();
delete ptr;

To erase memory leaking issue, you can store Object object directly in objVector instead of Object* . In this way, you don't have to worry about deleting objects. You can do like this,

int main()
{
    int choice;

    vector<Object> objVector; //create empty vector of "pointer-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)
    {
        objVector.emplace_back(); //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 (auto& obj : objVector)
        {
          obj.speak();
        }
    }
    }
    return 0;
}

This code is using c++11 feature. You can add object by calling emplace_back and delete object by just calling pop_back() . Isn't this sweet?

And one more thing. You forgot some code on header. This code cannot be compiled without these headers,

#include <iostream>
#include <vector>
using namespace std;

I'd happy if this code helps you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM