0

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?

7
  • 3
    PLEASE show some code! Commented May 6, 2017 at 1:17
  • 1
    Seems to me you should be creating a vector of TimelineItem pointers so that repeating entries refer to the same object in memory. Commented May 6, 2017 at 1:26
  • @OldProgrammer Added. From what I can tell, its because TimelineItem is creating its own instance of the variables declare at the top of driver.cpp, so is creating a new address, whereas TimelineItemRepeat is just taking the address of the variables. Hence, if I was to change the variables in driver.cpp, then TimelineItemRepeat would update. I'm just not sure how to pass the location of TimelineItem's datafields to TimelineItemRepeat. Commented May 6, 2017 at 1:26
  • @ApproachingDarknessFish I'm open to suggestions, but I am new to C++ so examples are much appreciated! Commented May 6, 2017 at 1:28
  • Is your intent to have a recurring event? Maybe you have lunch with the team every week, so you want to have a collection of the type of things you do, and a separate list of all the specific events? Commented May 6, 2017 at 1:44

2 Answers 2

2

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 TimelineItems. 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.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the in depth reply. Much appreciated. This approach is all good and well, expect that I need the start time and end time for each TimelineItem to be different e.g. a UNIX timestamp. Other than that, my current flow is that I have a object User that holds an object Timeline which holds some information including a vector of TimelineItems.
@Beardo Ah, seems to me then that you need two separate structs/classes, one to store an Event (i.e. "Dinner with team") and one to store a TimelineItem, and give each TimelineItem a timestamp and a pointer to an Event object. I'll come up with some example code.
Thanks for the extra edit! I'm gonna have some time today to give this a test. I'll advise on how it goes.
0
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;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.