Question

I have created a class Location, which is a parent class for classes City and Village. I have a vector<Location> and now I need to insert City or Village into this vector. I tried for example following:

    vector<Location> locations;
    locations.push_back(new City("New York", 9000, 1, 2));

or

    vector<Location> locations;
    Location* loc = new City("New York", 9000, 1, 2);
    locations.push_back(loc);

but nothing works. Can you give me an advice, please? I'm not a C++ programmer, I'm programming in Java normally, so please help me.

Was it helpful?

Solution

C++ new dynamically allocates, the type of the expression will be a pointer. In Java this is what (nearly) all object allocation is under the hood, you just don't see it. "names" in Java are references to objects allocated through the JVM (the process is very interesting, I recommend reading about it). However, Java copied C++'s syntax and made it do some very different things, so it's confusing to switch from Java to C++.

Since you are using polymorphism, you'll need a std::vector of pointers

std::vector<Location*> locations;
locations.push_back(new City{"New York", 9000, 1, 2});

When you are done with this vector you will need to delete everything you have allocated with new:

for (auto p : locations) {
    delete p;
}

Though all of this is best wrapped in another class that has the deletes handled in its destructor.

If you have no other pointers to these objects you can leverage unique_ptr as well, in which case you don't have to manually delete

std::vector<std::unique_ptr<Location>> locations;
locations.push_back(std::unique_ptr<Location>{new City{"New York", 9000, 1, 2}});

with a type alias:

using LocPtr = std::unique_ptr<Location>;
std::vector<LocPtr> locations;
locations.push_back(LocPtr{new City("New York", 9000, 1, 2)});

Depending on your compiler's level of C++1y support you could also do

std::vector<std::unique_ptr<Location>> locations;
locations.push_back(std::make_unique<City>("New York", 9000, 1, 2));

Another difference to be aware of: since you are using a pointer, you will have to use the -> operator instead of the .

locations.at(0)->name(); // assuming class Location{} has a name member function

p->attr is equivalent to (*p).attr

To make your class polymorphic it will need to have at least one virtual function. if nothing else, you should at least have virtual ~Location(){}. Note that any function not marked virtual won't have run time look up done on it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top