Declaring my member function parameters/arguments - c++

class Seller
{
private:
float salestotal; // run total of sales in dollars
int lapTopSold; // running total of lap top computers sold
int deskTopSold; // running total of desk top computers sold
int tabletSold; // running total of tablet computers sold
string name; // name of the seller
Seller::Seller(string newname)
{
name = newname;
salestotal = 0.0;
lapTopSold = 0;
deskTopSold = 0;
tabletSold = 0;
}
bool Seller::SellerHasName ( string nameToSearch )
{
if(name == nameToSearch)
return true;
else
return false;
}
class SellerList
{
private:
int num; // current number of salespeople in the list
Seller salespeople[MAX_SELLERS];
public:
// default constructor to make an empty list
SellerList()
{
num = 0;
}
// member functions
// If a salesperson with thisname is in the SellerList, this
// function returns the associated index; otherwise, return NOT_FOUND.
// Params: in
int Find ( string thisName );
void Add(string sellerName);
void Output(string sellerName);
};
int SellerList::Find(string thisName)
{
for(int i = 0; i < MAX_SELLERS; i++)
if(salespeople[i].SellerHasName(thisName))
return i;
return NOT_FOUND;
}
// Add a salesperson to the salespeople list IF the list is not full
// and if the list doesn't already contain the same name.
void SellerList::Add(string sellerName)
{
Seller(sellerName);
num++;
}
I have some issues with the parameters in my functions in my SellerList class. I want to add someone to the salespeople array so I have a record of all my sellers... Bob, Pam, Tim, etc... My constructor Seller(sellerName) creates a Seller with name sellerName.
How do I add this Seller to the Salespeople array and have capability of a way to pull the data back out and use it in more functions such as a Update function, or an output function?
MAX_SELLERS = 10.... I guess my issue is not knowing whether to use parameters of only
Add(string) or Add(Seller, string). Any help would be appreciated.

Not reinvent the wheel. Choose the container appropiate to your problem. In this case, because you are referencing/searching Sellers by a std::string, I suggest you to use a hash table like std::unordered_map (Or std::map search tree if you don't have access to C++11):
int main()
{
std::unordered_map<Seller> sellers;
//Add example:
sellers["seller name string here"] = /* put a seller here */;
//Search example:
std::unordered_map<Seller>::iterator it_result = sellers.find( "seller name string here" );
if( it_result != std::end( sellers ) )
std::cout << "Seller found!" << std::endl;
else
std::cout << "Seller not found :(" << std::endl;
}

How about using STD vector inside of SellerList instead of the array.
vector<Seller> x;
you can do x.push_back(Seller(...)) or x[0].SellerHasName() and x.size() will give you the number of sellers.

maybe something like this?
// Add a salesperson to the salespeople list IF the list is not full
// and if the list doesn't already contain the same name.
void SellerList::Add(string sellerName)
{
if(num < MAX_SELLERS)
salespeople[num++] = new Seller(sellerName);
}

Related

Vector Isn't Creating Multiple Class Objects

I have a vector that stores multiple class objects for later access. This way my program can create new objects during runtime. This is done like so:
vector<Person> peopleVector;
peopleVector.push_back(Person(name, age));
for (int i = 0; i < peopleVector.size(); i++) {
cout << peopleVector[i].name << endl;
}
This function should print out each objects "name" every time the code runs (it's a function that runs multiple times). However, when I run this, somehow the vector does not increase in size. If you add cout << peopleVector.size(); to that code, you will find that each time it runs, it gets one (obviously assuming you also have the class code which I have below).
I'm curious why I can't create multiple objects in the class.
Class.h
#pragma once
#include <iostream>
using namespace std;
class Person {
public:
Person(string personName, int personAge);
string name;
int age;
};
Person::Person(string personName, int personAge) {
name = personName;
age = personAge;
}
Main.cpp
#include "Class.h"
#include <random>
int main() {
// Necessary for random numbers
srand(time(0));
string name = names[rand() % 82]; // Array with a lot of names
int age = 4 + (rand() % 95);
}
// Create a new person
void newPerson(string name, int age) {
vector<Person> peopleVector;
peopleVector.push_back(Person(name, age));
for (int i = 0; i < peopleVector.size(); i++) {
cout << peopleVector[i].name << endl;
}
}
Just FYI those #includes might be a little bit off because I took that code out of a large section that had like 15 includes.
You are creating an empty vector each time you call your newPerson() function, and then you add a single person to it.
You then display the contents of that vector. What else can it contain, other than the single person that you added?
Problem
Every time a function runs, all local variables inside the function are re-created in their default state. That means that every time you call newPerson, it just recreates peopleVector.
Solution
There are two solutions:
Have newPerson take a reference to a vector, and add it on to that
make peopleVector static, so that it isn't re-initialized every time
First solution:
// Create a new person; add it to peopleVector
// The function takes a reference to the vector you want to add it to
void newPerson(string name, int age, vector<Person>& peopleVector) {
peopleVector.push_back(Person(name, age));
for (int i = 0; i < peopleVector.size(); i++) {
cout << peopleVector[i].name << endl;
}
}
Second solution: mark peopleVector as static
// create a new person; add it to peopleVector
void newPerson(string name, int age) {
// Marking peopleVector as static prevents it from being re-initialized
static vector<Person> peopleVector;
peopleVector.push_back(Person(name, age));
for (int i = 0; i < peopleVector.size(); i++) {
cout << peopleVector[i].name << endl;
}
}

void class Arrays Sequential and Binary Search Using

I'm currently at my wits end trying to figure out how to do this, and was hoping someone could help.
The objectives the assignment is to:
Display the original sorted array of student records.
Display the sequential search result of student records.
Display the binary search result of student records.
The Full Instructions are:
a. Create three array of 12+ students records including ID’s, student names, and
the corresponding e-mail address’,– student ID’s are sorted in order. (No sort program needed for now.)
b. Sequential Search five ID’s which are from the sorted array and a 6th ID which is not from the array.
c. Binary Search five ID’s which are from the sorted array and a 6th ID which is not from the array.
d. Execution and output:
Display the original sorted array of student records.
Display the sequential search result of student records.
Display the binary search result of student records.
Any Help would be greatly appreciated
#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
struct Student {
string name;
int stuID;
string email;
};
// Show the student information
void showAllInfo(Student *studentArray, int stuCount) {
cout << "Student Info: "<<endl <<endl<<
"\t\tStudent Name"<<"\t\tStudent ID"<<"\t\tStudent Email"<<endl<<endl ;
for (int i = 0; i < stuCount; i++)
{
cout<<"\t\t"<< studentArray[i].name<<"\t\t"<<studentArray[i].stuID<<"\t\t\t"<< studentArray[i].email<<endl;
}
cout << endl;
}
//Sort out the arrays for the student information
void firstArray()
{
Student studentArray[12];
studentArray[0].name = "Bob McBoberston";
studentArray[0].stuID = 00;
studentArray[0].email = "BMcboberts#txstate.edu";
studentArray[1].name = "Shelby Donald";
studentArray[1].stuID = 1;
studentArray[1].email = "SDonald#txstate.edu";
studentArray[2].name = "Ronald Mcdonald";
studentArray[2].stuID = 2;
studentArray[2].email = "RMcdonald#txstate.edu";
studentArray[3].name = "Dick Cheney";
studentArray[3].stuID = 3;
studentArray[3].email = "DCheney#txstate.edu";
studentArray[4].name= "Ben Dover";
studentArray[4].stuID=4;
studentArray[4].email="BDover#txstate.edu";
studentArray[5].name="Ash Katchum";
studentArray[5].stuID=5;
studentArray[5].email="AKatchum#txstate.edu";
studentArray[6].name="Brock Whatever";
studentArray[6].stuID=6;
studentArray[6].email="BWhatevr#txstate.edu";
studentArray[7].name="Yugi Oh";
studentArray[7].stuID=7;
studentArray[7].email="YugiOh#txstate.edu";
studentArray[8].name="Johnny Bravo";
studentArray[8].stuID=8;
studentArray[8].email="JBravo#txstate.edu";
studentArray[9].name="Tom N. Jerry";
studentArray[9].stuID=9;
studentArray[9].email="Tnjerry#txstate.edu";
studentArray[10].name="Fred Flinstone";
studentArray[10].stuID=10;
studentArray[10].email="FFlinstone#emial.com";
studentArray[11].name="Son Goku";
studentArray[11].stuID=11;
studentArray[11].email="sGoku#txstate.edu";
studentArray[12].name="Johnny Test";
studentArray[12].stuID=12;
studentArray[12].email="JTest#txstate.edu";
}
void secondArray()
{
Student studentArray2[12];
studentArray2[0].name = "Rick Sanchez";
studentArray2[0].stuID = 13;
studentArray2[0].email = "RSanchez#txstate.edu";
studentArray2[1].name="Morty Smith";
studentArray2[1].stuID = 14;
studentArray2[1].email = "MSmith#txstate.edu";
studentArray2[2].name = "Summer Smith";
studentArray2[2].stuID = 15;
studentArray2[2].email = "SSmith#txstate.edu";
studentArray2[3].name = "Jerry Smith";
studentArray2[3].stuID = 16;
studentArray2[3].email = "JSmith#txstate.edu";
studentArray2[4].name="Mr. Meeseeks";
studentArray2[4].stuID=17;
studentArray2[4].email="MMeeseeks#txstate.edu";
studentArray2[5].name="Mr. PoopyButtHole";
studentArray2[5].stuID=18;
studentArray2[5].email="MPoopyButt#txstate.edu";
studentArray2[6].name="Tiny Rick";
studentArray2[6].stuID=19;
studentArray2[6].email="TRick#txstate.edu";
studentArray2[7].name="Pickle Rick";
studentArray2[7].stuID=20;
studentArray2[7].email="PRick#txstate.edu";
studentArray2[8].name="Beth Smith";
studentArray2[8].stuID=21;
studentArray2[8].email="BSmith#txstate.edu";
studentArray2[9].name="Bird Person";
studentArray2[9].stuID=22;
studentArray2[9].email="BmPerson#txstate.edu";
studentArray2[10].name="Squanchy";
studentArray2[10].stuID=23;
studentArray2[10].email="Squanchy#txstate.edu";
studentArray2[11].name="King Flippy Nips";
studentArray2[11].stuID=24;
studentArray2[11].email="KFlippyNipa#txstate.edu";
studentArray2[12].name="Mr> Goldenfold";
studentArray2[12].stuID=25;
studentArray2[12].email="MGoldenfold#txstate.edu";
}
void thirdArray()
{
Student studentArray3[13];
studentArray3[0].name = "Santa Claus";
studentArray3[0].stuID = 26;
studentArray3[0].email = "SClause#txstate.edu";
studentArray3[1].name = "Jason Riha";
studentArray3[1].stuID = 27;
studentArray3[1].email = "JRiha#txstate.edu";
studentArray3[2].name = "B-Rad Cragg";
studentArray3[2].stuID = 28;
studentArray3[2].email = "BRad#txstate.edu";
studentArray3[3].name="Roger Legrand";
studentArray3[3].stuID = 29;
studentArray3[3].email = "RLegrand#txstate.edu";
studentArray3[4].name="David De La O";
studentArray3[4].stuID=30;
studentArray3[4].email= "DDelao#txstate.edu";
studentArray3[5].name="Ian Sporn";
studentArray3[5].stuID=31;
studentArray3[5].email="ISporn#txstate.edu";
studentArray3[6].name="Morgan Taylor";
studentArray3[6].stuID=32;
studentArray3[6].email="Mytaylor#txstate.edu";
studentArray3[7].name="Sam Huggins";
studentArray3[7].stuID=33;
studentArray3[7].email="SHuggins#txstate.edu";
studentArray3[8].name="Shaun Huggins";
studentArray3[8].stuID=34;
studentArray3[8].email="ShuHuggins#txstate.edu";
studentArray3[9].name="Serena Huggins";
studentArray3[9].stuID=35;
studentArray3[9].email="SerHuggins#txstate.edu";
studentArray3[10].name="Kylie Parziale";
studentArray3[10].stuID=36;
studentArray3[10].email="KParziale#txstate.edu";
studentArray3[11].name="Jimmy Fallon";
studentArray3[11].stuID=37;
studentArray3[11].email="JFallon#txstate.edu";
studentArray3[12].name="Tom Goat Brady";
studentArray3[12].stuID=38;
studentArray3[12].email="TGBrady#txstate.edu";
studentArray3[13].name="Harry Giblets";
studentArray3[13].stuID=39;
studentArray3[13].email="HGiblets#txstate.edu";
}
int main() {
int stuCount = 39;
firstArray();
secondArray();
thirdArray();
showAllInfo(studentArray,stuCount);
return 0;
}
So you have a few problems. The first is that your arrays are declared inside the functions you've written, so no other code is going to be able to access them. You should declare your arrays inside the main function so that they can be passed as parameters to other functions. If you don't know how to pass an array as a parameter then the rest of this assignment is going to be difficult for you.
Anyway lets start like this, you don't need to write function to set up your arrays, you can do it directly in main, like this
int main()
{
Student firstArray[12] = {
{ "Bob McBoberston", 0, "BMcboberts#txstate.edu" },
...
};
Student secondArray[12] = {
...
};
Student thirdArray[12] = {
...
};
...
}
Now that the arrays are set up you need to write a function to do the sequential search (binary search is more complex, so leave that one for now).
Think about what parameters a function needs and what return value it has. This is always the first step when writing a function, but it's also one that many newbies struggle with.
In the case a sequential search function it needs to know 1) which array is it going to search, 2) how big that array is, 3) what id you are searching for. These are the parameters. It seems reasonable for the function to return the index in the array of the person it's found, or a special value -1 if it doesn't find the id. That's not the only way to do it, but it'll do for now. So putting that together we have
// look for 'id' in 'array' and returns the index if found or -1 if not found
int sequential_search(Person array[], int array_size, int id)
{
...
}
In your main function you would use this function something like this
int main()
{
...
// look for person with id 5
int id = 5;
int index = sequential_search(firstArray, 12, id);
if (index == -1)
cout << "ID " << id << " not found\n";
else
cout << "ID " << id << " is " << firstArray[index].name << "\n";
}
Get the idea? Hopefully this gives you a start. You can do the rest, and ask again if you get into difficulties.

C++ Graph data Structure

I am writing a graph implementation in c++ where the cities are vertices, flights from one city to another city represent an edge, and the weights are the distances between those cities. The vertices,edges, and weights are stored in a file and when the program runs it would load the vertices, edges, and weights into the program. I am using an adjacency matrix where it represents the edges.
Now when the program runs it will prompt the user to either:
Choose Departure city
Exit. Option two just terminates the program.
If the user chooses option one, then it will list all the cities from the file. There a seven cities I chose. So it will look like 1.)Los Angeles 2.) New York 3.) Miami and so on until option 7. When the user chooses an option it will then list all the destination cities except the departure city the user chose. There would be three possibilities once the user chooses his destination city.
Now the first possibility would be there would be no direct or through connection between city A and city B and the program will output, No destination between [departure city] and [destination city] , press any key to return. Once the user presses any key, the menu will display again. The Second possibility would be if there is a direct connection between the city then the program would output the direct connection between [departure city]-[destination city] = [miles] and the miles between the city, or if there isn't a direct connection it will say no direct connection and the user can go back to the menu.
The third possibility would be that there would be a through connection and it will show the departure city and destination city with all the cities between them and the total miles it covers between them and the user can press any key to return to the menu.
Now the problem I"m having is getting the info from the file, I can't figure out how to get the info from the file or how to write the file so the program knows which are the vertices,edges,and weights. Also, how to display the cities and which have the direct connection, through connection, or no connection at all.
include <iostream>
#include <fstream>
#pragma once
const int NULL_EDGE = 0;
typedef std::string String;
class GraphType
{
private:
int edges[50][50];
int m_numVertices;
int m_maxVertices;
int m_distance;
String* m_vertices;
bool* marks; // marks[i] is the mark for vertices[i]
int IndexIs(String*, String);
public:
GraphType();
~GraphType();
bool isEmpty() const;
bool isFull(); //to do
int GetWeight(String, String); // to do
void ClearMarks(); // to do
void MarkVertex(String) // to do
bool isMarked(String) // to do
void addVertex(String);
void addEdge(String, String, int);
void displayCities();
};
#include "GraphType.h"
GraphType::GraphType()
{
m_maxVertices = 50;
m_distance = 0;
m_vertices = new String[m_maxVertices];
marks = new bool[50];
std::ifstream loadFile;
loadFile.open("load.txt");
if (loadFile.fail())
std::cout << " Error opening load.txt\n";
else
{
//stuck here
}
loadFile.close();
}
GraphType::~GraphType()
{
delete[] m_vertices;
delete[] marks;
}
int GraphType::IndexIs(String* vertices, String vertex)
{
int index = 0;
while (!(vertex == m_vertices[index]) == 0)
index++;
return index;
}
void GraphType::addVertex(String vertex)
{
m_vertices[m_numVertices] = vertex;
for (int i = 0; i < m_numVertices; i++)
{
edges[m_numVertices][i] = NULL_EDGE;
edges[i][m_numVertices] = NULL_EDGE;
}
m_numVertices++;
}
void GraphType::addEdge(String startVertex, String destVertex, int weight)
{
int row;
int col;
row = IndexIs(m_vertices, startVertex);
col = IndexIs(m_vertices, destVertex);
edges[row][col] = weight;
}
void GraphType::displayCities()
{
//stuck here
}
bool GraphType::isEmpty() const
{
return (m_numVertices == 0);
}
#include "GraphType.h"
int FlyMenu();
void CitiesMenu(GraphType&);
int main()
{
int choose;
GraphType gt;
do
{
choose = FlyMenu();
switch (choose)
{
case 1: CitiesMenu(gt);
break;
case 2:
break;
default: std::cout << " Invalid Input\n";
break;
}
} while (choose != 2);
return 0;
}
int FlyMenu()
{
int option;
std::cout << " 1.) Choose Depature City\n";
std::cout << " 2.) Exit\n";
std::cout << " Enter option: ";
std::cin >> option;
return option;
}
void CitiesMenu(GraphType& gt)
{
gt.displayCities();
}
I know about the depth Traversal and breadth Traversal algorithms to see if there is a connection between a city or not, but I don't know how to implement them for this scenario. I can't use the Standard Template Library, only std::vector. I was thinking about writing another class, but I don't know what what that class will help me with.
From what I got you have two questions:
read / write from file: the simplest solution would be freopen.
freopen("input","r",stdin)
freopen("output","w",stdout)
now every cin & cout operation will be done on the files you defined on freopen
implementing DFS / BFS: I will code the simplest type of DFS for you and you have to edit it to suite you program.
bool visit[MAX_CITY + 10];
void DFS(int x){
visit[x] = 1;
for (int i=1;i<=MAX_CITY;i++){
int nx = i;
if (adj[x][i] == -1) continue; // a cost of -1 means no flight
if (visit[nx]) continue;
DFS(nx);
}
}

Getline() and cin manipulate dynamic array

I'm totally lost and confused and could use some help.
I'm currently working on a small command line-based game. For this I wrote a class Inventory, dynamically creating an array of invSpace-objects, each space representing a pair of a pointer to an Item (another class of mine) and a integer, depicting a quantity. Here's the code:
class invSpace {
public:
Item *item;
int quantity;
invSpace() {
item = NULL;
quantity = 0;
}
};
class Inventory {
private:
invSpace* spaces = NULL;
size_t size;
public:
int free_space() {
int free = 0;
for (int i = 0; i < size; i++) {
if (spaces[i].item == NULL) {
free++;
}
}
return free;
}
Inventory() {}
Inventory(size_t new_size) {
size = new_size;
spaces = new invSpace[size];
for (int i = 0; i < size; i++) { //I know this is obsolete because
spaces[i].item = NULL; //of the invSpace constructor, I
spaces[i].quantity = 0; //just did this for testing
}
~Inventory() {
delete[] spaces;
}
invSpace& operator[](int index) {
return spaces[index];
}
};
There are some more methods in this class, like for adding, deleting and searching for items, but those don't matter now. So this is basically just a simple array within one object, dynamically allocating memory in the constructor and with some extra methods. After being created, the array contains zero elements, or Items, so the free_space() method should return the size of the array. But it doesn't. It returns about half of the size.
My first thought was that something went wrong with the allocation. But at a second glance I noticed that the Inventory is totally fine directly after being created; with exactly as many spaces as requested, all of them set to item=NULL/quantity=0. But after a call of getline() at the start of main() that scans user input and saves it to a string for further analyzing, some spaces get filled with random addresses and integers.
Even stranger, with each new call of getline() some spaces are freed, some others filled. As far as my debugging, experimenting and testing goes, none of these addresses belong to any variable in my program, they are just plain random. Also, at no point is there be any interference with the Inventory and the getline() function or the string it returns. In fact, after being created, no part of this object is used anywhere in the code beside the free_space() method. What's even stranger is that spaces in the Inventory class is marked private, so a method is required to meddle with this pointer/array (or so I would expect).
This problem occurs with getline() and cin but not with any of C's <stdio.h> input stream functions. Using malloc() instead of new[] makes no difference. Of course, I could use something like scanf() for the reading from the console. Still, I just want to know why all these things happen. I have absolutely no idea.
Thanks in advance for every answer!
EDIT:
I narrowed the whole code so that it still produces the same error, also changed free_space() so that it prints adress and integer if present:
#include <iostream>
#include <string>
#include <map>
using namespace std;
class Item {
public:
static map<string, Item*> itemlist;
string name;
string description;
Item() {}
Item(const string new_name, const string new_description) {
name = new_name;
description = new_description;
itemlist.insert(pair<string, Item*> (name, this));
}
};
map<string, Item*> Item::itemlist;
/*The more Items are declared, the more random adresses appear in the
inventory*/
Item item01("sword", "A sharp and deadly weapon.");
Item item02("shield", "This will protect you. To a certain extent.");
Item item03("stick", "What is this for exactly?");
Item item04("bottle of water", "A bottle full of refreshing spring water.");
class invSpace {
public:
Item *item;
int quantity;
invSpace() {
item = NULL;
quantity = 0;
}
};
class Inventory {
private:
invSpace* spaces = NULL;
size_t size;
public:
int free_space() {
int free = 0;
for (int i = 0; i < size; i++) {
if (spaces[i].item == NULL) {
free++;
cout << i << " = free" << endl;
}
else {
cout << spaces[i].item << " / " << spaces[i].quantity << endl;
}
}
return free;
}
Inventory() {}
Inventory(size_t new_size) {
size = new_size;
spaces = new invSpace[size];
for (int i = 0; i < size; i++) {
spaces[i].item = NULL;
spaces[i].quantity = 0;
}
}
~Inventory() {
delete[] spaces;
}
};
class Player {
public:
string name;
Inventory inventory;
Player(const string new_name) {
inventory = Inventory(40);
name = new_name;
}
};
Player player("Me");
int main() {
string input;
//Inventory inventory(40); //no error when declared outside the Player class
while (1) {
cout << "\n>> ";
getline(cin, input);
if (input == "x") {
break;
}
else {
player.inventory.free_space();
}
}
}
Some things I noticed: No error occurs if the inventory isn't part of a Player-object. If it is but no Items are declared only the first inventory space receives a random adress (and int value) after the first call of getline().
The more Items there are, the more random adresses I get, it seems...

Such a thing as C++ design pattern to avoid pointers?

I have a class hierarchy as shown in the example below, where a State contains a list of ZipCodes and a list of Citys, each of which contain pointers to the ZipCodes.
The goal is to be able to update the ZipCodes without needing to update Citys (or to create new instances of City).
The C++ code below meets this requirement, but it uses pointers, which I prefer to avoid because of this and that. How can I re-design this [naive] implementation so that it doesn't rely on pointers? Thanks for any help!
EDIT: Updated code below to use boost::shared_ptr instead of raw pointers. Note that State, City, and ZipCode are just example names, and they turned out to be poor choice names (I could've picked "A", "B", and "C") because the actual code allows the equivalent of City to share ZipCodes.
#include <iostream>
#include <vector>
#include <boost/shared_ptr.hpp>
using namespace std;
/**
* Zone Improvement Plan (ZIP) code
*/
class ZipCode {
public:
ZipCode() : code_(0), plus4_(0) {}
ZipCode(int code, int plus4 = 0) : code_(code), plus4_(plus4) {}
virtual ~ZipCode() {};
int code() const { return code_; }
int plus4() const { return plus4_; }
void set_code(int code) { code_ = code; }
void set_plus4(int plus4) { plus4_ = plus4; }
private:
int code_;
int plus4_;
};
typedef boost::shared_ptr<ZipCode> ZipPtr;
/**
* City points to one or more zip codes
*/
class City {
public:
const vector<ZipPtr>& zip() const { return zip_; }
void add_zip_ptr(const ZipPtr x) { if (x != NULL) zip_.push_back(x); }
private:
// TODO: this vector should be a hash set
vector<ZipPtr> zip_;
};
/**
* State contains cities, each of which has pointers to
* zip codes within the state.
*/
class State {
public:
const vector<City>& city() const { return city_; }
const vector<ZipPtr>& zip() const { return zip_; }
const ZipPtr zip_of(int code) const {
for (size_t i = 0; i < zip_.size(); i++) {
if (zip_[i]->code() == code) {
return zip_[i];
}
}
return ZipPtr();
}
void add_city(const City& x) { city_.push_back(x); }
void add_zip(int code) { zip_.push_back(ZipPtr(new ZipCode(code))); }
private:
// TODO: these vectors should be hash sets
vector<City> city_;
vector<ZipPtr> zip_;
};
int main() {
State texas;
City dallas, houston;
// create state ZIPs
texas.add_zip(75380);
texas.add_zip(75381);
texas.add_zip(77219);
texas.add_zip(77220);
// point city ZIPs to the ones we just created
dallas.add_zip_ptr(texas.zip_of(75380));
dallas.add_zip_ptr(texas.zip_of(75381));
houston.add_zip_ptr(texas.zip_of(77219));
houston.add_zip_ptr(texas.zip_of(77220));
// print all ZIPs
cout << "ZIPs in Texas: " << endl;
const vector<ZipPtr>& zips = texas.zip();
for (size_t i = 0; i < zips.size(); i++) {
cout << " " << zips[i]->code() << endl;
}
cout << "ZIPs in Dallas, Texas: " << endl;
const vector<ZipPtr> zip_ptrs1 = dallas.zip();
for (size_t i = 0; i < zip_ptrs1.size(); i++) {
cout << " " << zip_ptrs1[i]->code() << endl;
}
cout << "ZIPs in Houston, Texas: " << endl;
const vector<ZipPtr> zip_ptrs2 = houston.zip();
for (size_t i = 0; i < zip_ptrs2.size(); i++) {
cout << " " << zip_ptrs2[i]->code() << endl;
}
// change a state ZIP...
cout << "Changing Houston's ZIP 77220..." << endl;
ZipPtr z = texas.zip_of(77220);
if (z != NULL) z->set_code(88888);
// ...and show the ZIPs of the affected city
cout << "ZIPs in Houston, Texas: " << endl;
const vector<ZipPtr> zip_ptrs3 = houston.zip();
for (size_t i = 0; i < zip_ptrs3.size(); i++) {
cout << " " << zip_ptrs3[i]->code() << endl;
}
return 0;
}
I see the situation as two 1:n relationships
State : City == 1 : n
City : Zipcode
== 1 : n
Based on that, I think that the State containing
vector<ZipCode> zip_;
is not sound.
I might do
class State {
vector< City > cities_in_state_;
};
class City {
vector< Zipcode > zips_in_city_;
};
This does not require pointers.
Unless you want to duplicate your ZipCode objects, you fall into this category of usage (described in your first link):
The Bar instance is actually managed
by some other part of your program,
whereas the Foo class just needs to be
able to access it.
It seems like a legit use.
However, you might want to consider the copy option (to permanently avoid problems if the vector has to reallocate its data) or make State aggregate ZipCodes from its Cities instead of distributing them ZipCodes.
The copy simply implies that you stop using pointers in City. Aggregating the ZipCodes means that instead of giving State a list of ZipCodes, you would give City the list of ZipCode instances, and when calling zip_of, you would iterate through the cities and iterate through their ZipCode collection.