do my constructor need attractions vector as parameter?
I don't think so. Since the attractions belong to the city, only the city should know how they are stored. I also would not return the vector of attractions since it breaks the encapsulation. Instead I would create some functions inside the city class to retrieve an attraction :
1 2 3
int AttractionCount();
void AddAttraction(Attraction attr);
Attraction& GetAttraction(int index);
Also I would think twice if you really need pointers inside your vector. Pointers can cause trouble if not used with caution. Think about a normal variable or at least a smart_ptr.
I'd advice changing it to "One invalid pointer can do more harm than 10 gotos". There circumstances where using a pointer makes perfect sense, that's why we have them in the first place. Of course, using them the wrong way can result in horrific results (note the can, strictly speaking, anything could happen).
Of course, if you want to use a more safe approach around the pointers, you could change your method signatures to accept references, as these are much harder to invalidate, but still use pointers at the heart of your application. An example:
1 2 3 4 5 6 7 8 9 10 11
class City
{
private:
/*All fields*/
vector<Attraction*> attractions;
public:
/*Other methods*/
int AttractionCount() { return attractions.size();}
void AddAttraction(Attraction& attr) {attractions.push_back(&attr);}
Attraction& GetAttraction(int index) {return *(attractions.at(index));}
};
It still works the same as the pointer version, although this time you can be sure you will not have invalid pointer values in your attractions vector (at least, as long as the underlying objects remain valid).
why the hell u guys keep on saying pointer is harm?
in OOP passing pointers around and between objects is considered a bad design.
better approach is by using signals and callbacks.
in other cases, it's better to use smart pointers.
for your particular case, to make the code OOP you could have create a separate (abstract) "attraction" class and then let the city inherit that class and overload provided methods to access attractions.
then for example the calling code could use a pointer to attractions initialized with city object, and use provided interface, in which case using a pointer makes sense.
later you can just cast the pointer down to city to access city interface. meaning you only have one "universal" pointer to worry about.
attractions can be located in villages as well or other places so it makes sense to have common base attraction class. this provides flexibility for extending your code later and not worry about rewriting the code to fulfill possible new ideas.
to make the code OOP you could have create a separate (abstract) "attraction" class and then let the city inherit that class and overload provided methods to access attractions.
This doesn't make any sense to me. A city is not an attraction but has attractions. So a collection of attractions inside the city class is a good idea - IMHO - only is there no need to store the attactions as raw pointers.
I think that stating "pointers are bad" is the wrong way of putting it. It's true you can easily abuse them and new programmers often abuse them, running into undefined behavior along the way. It does teach you how to use them though.
Pointers are useful in a lot of situations, that's the reason we have them. In most of these situations, you can wrap them in a smart pointer to automate memory management for you, but there are cases where you can't. Lately I've been programming low-level code. It's hard to not use pointers in these scenarios and using workarounds just to not use pointers can lead to more obscure code than using a pointer would.
When you think up a good solution to a problem and a pointer is involved in this solution, don't shy away from using it just because there's a pointer involved. Not all code using a pointer is bad design by default. Too bad I tend to be one of the fewer who tend to think this way nowadays.
An example to demonstrate where pointers could be useful:
//Three integers
int a = 2;
int b = 3;
int c = 4;
//And a vector containing pointers to integers
std::vector<int*> integers;
integers.push_back(&a); //Push a pointer to a in the vector
integers.push_back(&b); //Push a pointer to b
integers.push_back(&c); //And last but not least, a pointer to c
//Now we loop over the elements in the vector
for(std::vector<int*>::size_type i = 0; i < integers.size(); ++i)
{
//Fetch the element in the vector
int* element = integers[i];
//Increase the element
++(*element);
}
//Now a = 3, b = 4 and c = 5
//Using a vector<int> would not modify a, b and c
This code uses pointers as a form of references in a vector. A standard std::vector cannot store references, but it can store raw pointers. This way we can use a reference mechanism in the containers of the standard library.
One can do a lot just using the STL containers, and have no need for pointers unless it's to use virtual polymorphism. If one does this, then the code should be more safe. After all the STL was designed to be safe and easy to use.
A plain lvalue reference also means there is often no need for a raw pointer.
Then there are smart pointers.
Also, there is std::reference_wrapper so that references can be stored in a container.
There are other things such as move semantics, copy elision, perfect forwarding, use of rvlaue references, varadiac templates, and more probably - which mean that raw pointers are no longer needed for such things.
So all that applies to general programming, for low level stuff pointers do have a use. And this is an example of where there is one advice to beginner & intermediate programmers, versus different practises by expert coders, as in global variables, goto, exceptions (situations where they shouldn't be used), new & delete, char arrays, use of float, macros, pointer arithmetic.
@Shadowwolf
I know it is a simple example, but not sure why you want to modify the elements of the vector, and their original input variables a,b ,c ?
The example demonstrated a simple system for implementing references. One example could be to use them in a standard vector (even though std::reference_wrapper exists for this purpose, but that's why it's an example), but a more commonly (and usually more complex) scenario is to interface with C code, which nearly exclusively uses pointers for this purpose.
In the example only the original input values are modified through the pointer. The elements of the vector are not modified.
Even though I agree pointers shouldn't be used as a default alternative. It isn't a good idea to tell a beginner to never use a pointer, then later tell them that they can be used. This is often more confusing than explaining when to use pointers, and when not to.