Reputation: 1507
I am making a Timeline application. A timeline can have a TimelineItem. If an item repeats, I want the TimelineItem to hold a vector of type TimelineItemRepeat where the only difference between the values in TimelineItem and TimelineItemRepeat are the start and end times.
As such, I want to make it that whenever I make an edit to an instance of TimelineItem e.g. tl_item.setLocation("Paris"), all of the TimelineItemRepeat instances that relate to the TimelineItem will also update.
I am trying to achieve this by creating the TimelineItem instance and then passing the memory location of each of TimelineItem's variables to the constructor for TimelineItemRepeat.
Currently, I am declaring the variables and passing it to both of my constructors, however, it isn't working. My code:
driver.cpp
short int type = 0;
string desc = "Lunch with Team";
string loc = "New York Office";
time_t start = time_t(0);
time_t end = time_t(600);
vector<TimelineItemRepeat> repeats;
TimelineItem tl_item(type, desc, loc, start, end);
repeats.push_back(TimelineItemRepeat(type, desc, loc, start, end, tl_item));
tl_item.setLinkedItems(repeats);
std::cout << tl_item.toString() << endl;
std::cout << tl_item.getLinkedItems()[0].toString() << endl;
tl_item.setDescription("Dinner with Team");
std::cout << tl_item.toString() << endl;
std::cout << tl_item.getLinkedItems()[0].toString() << endl;
Outputs
TimelineItem Description Address: 0x7fff5ebcb600
0 Lunch with Team 0 600 1
TimelineItemRepeat Description Address: 0x7fff5ebcb6a0
0 Lunch with Team 0 600
TimelineItem Description Address: 0x7fff5ebcb600
0 Dinner with Team 0 600 1
TimelineItemRepeat Description Address: 0x7fff5ebcb6a0
0 Lunch with Team 0 600
Am I going about this the wrong way?
Upvotes: 0
Views: 89
Reputation: 14313
Am I going about this the wrong way?
I would say yes. It seems you're trying to get multiple positions in the vector to reference the same object. This can easily be accomplished by creating a vector of pointers to TimelineItem
s. This way we can have a single vector, call it timeline
.
If you don't know what pointers are or how they work, learn about them before tackling any more C++.
Let's say we want the same timeline item to be repeated three times in our vector. At its most basic, the setup looks like this.
//Create a pointer to a dynamically allocated object
TimelineItem *tl_item = new TimelineItem(type, desc, loc, start, end);
vector<TimelineItem*> timeline; //vector of pointers instead of objects.
//all entries point to the same object
timeline.push_back(tl_item);
timeline.push_back(tl_item);
timeline.push_back(tl_item);
Now, any changes you make to timeline[0]
will show up in timeline[1]
and [2]
, since they all point to the same object. Since these are pointers, not objects, you'll have to use ->
instaed of .
to access the members, e.g.
tl_item->setDescription("Dinner with team");
Has the same effect as
timeline[0]->setDescription("Dinner with team");
timeline[1]->setDescription("Dinner with team");
timeline[2]->setDescription("Dinner with team");
However, using pointers means we now need to worry about memory allocation. Once you're done with tl_item
and timeline
, you need to clean up the memory you allocated earlier with new
:
delete tl_item; //destroys the object; all pointers now point to garbage memory.
This will work for very simple programs, but I highly recommend looking into std::shared_ptr if you care at all about how modern C++ is best written.
EDIT:
Based on comments, what you actually need is two separate classes, one to represent events and one to store timeline items. Simplistic example:
class Event {
string description;
};
class TimelineItem {
Event *event;
timestamp time; //however you want to store this
//whatever constructors, getters, setters you need
};
vector<TimelineItem> timeline;
Event *dinner = new Event("Dinner with team");
//Let's say we have dinner twice this week. Set these to whatever.
timestamp first_item_ts = ... ;
timestamp second_item_ts = ... ;
//Two separate items in the timeline, at different timestamps, but both refer to the same Event object using pointers!
timeline.push_back(TimelineItem(dinner, first_item_ts));
timeline.push_back(TimelineItem(dinner, second_item_ts));
Now if we change the common event object, both timeline items will show it. All of the following have the same effect:
timeline[0].event->setDescription("Breakfast with team")
timeline[1].event->setDescription("Breakfast with team")
event->setDescription("Breakfast with team")
I've left out a lot of the code here in order to make it clear what the setup is. Hopefully how it works is clear.
Upvotes: 2
Reputation: 717
repeats.push_back(TimelineItemRepeat(type, desc, loc, start, end, tl_item));
Above line creates brand new object(completely independent) in vector, only copying your values, so if you want the values to update, you should declare repeats as vector of pointers to TimelineItem's:
vector<TimelineItem*> repeats;
and then, instead of adding object, you shold add address of your object:
TimelineItem tl_item(type, desc, loc, start, end);
repeats.push_back(&tl_item);
The only difference in your code will be that you must use ->
instead of .
in this statement:
std::cout << tl_item.getLinkedItems()[0]->toString() << endl;
Upvotes: 0