使用完全相同的变量创建两个对象

时间:2017-05-06 01:16:49

标签: c++

我正在制作时间轴应用程序。时间轴可以有一个TimelineItem。如果一个项目重复,我希望TimelineItem包含一个TimelineItemRepeat类型的向量,其中TimelineItem和TimelineItemRepeat中值之间的唯一差异是开始和结束时间。

因此,每当我对TimelineItem的实例进行编辑时,我都希望这样做。 tl_item.setLocation(“Paris”),与TimelineItem相关的所有TimelineItemRepeat实例也将更新。

我试图通过创建TimelineItem实例然后将每个TimelineItem变量的内存位置传递给TimelineItemRepeat的构造函数来实现此目的。

目前,我正在声明变量并将其传递给我的两个构造函数,但是,它无法正常工作。我的代码:

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;

输出

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

我是以错误的方式解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

  

我是以错误的方式解决这个问题吗?

我会说是的。看起来你正试图在向量中获得多个位置来引用同一个对象。这可以通过创建指针TimelineItem的向量来轻松完成。这样我们就可以有一个向量,称之为timeline

如果您不知道指针是什么或它们如何工作,请在处理更多C ++之前了解它们。

假设我们希望在我们的向量中重复相同的时间轴项目三次。在最基本的情况下,设置看起来像这样。

//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);

现在,您对timeline[0]所做的任何更改都会显示在timeline[1][2]中,因为它们都指向同一个对象。由于这些是指针,而不是对象,因此您必须使用-> .的{​​{1}}来访问成员,例如。

tl_item->setDescription("Dinner with team"); 

具有相同的效果
timeline[0]->setDescription("Dinner with team");
timeline[1]->setDescription("Dinner with team");
timeline[2]->setDescription("Dinner with team");

但是,使用指针意味着我们现在需要担心内存分配。完成tl_itemtimeline后,您需要使用new清理之前分配的内存:

delete tl_item; //destroys the object; all pointers now point to garbage memory.

这适用于非常简单的程序,但如果您完全关心现代C ++的编写方式,我强烈建议您查看std::shared_ptr

编辑:

根据评论,您实际需要的是两个单独的类,一个用于表示事件,另一个用于存储时间轴项。简单的例子:

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));

现在,如果我们更改公共事件对象,则两个时间轴项都会显示它。以下所有都具有相同的效果:

timeline[0].event->setDescription("Breakfast with team")

timeline[1].event->setDescription("Breakfast with team")

event->setDescription("Breakfast with team")

我在这里遗漏了很多代码,以便明确设置是什么。希望它的工作原理很清楚。

答案 1 :(得分:0)

repeats.push_back(TimelineItemRepeat(type, desc, loc, start, end, tl_item));

上面的行在向量中创建全新的对象(完全独立),只复制你的值,所以如果你想要更新值,你应该将重复声明为指向TimelineItem的指针的向量:

vector<TimelineItem*> repeats;

然后,不是添加对象,而是添加对象的地址:

TimelineItem tl_item(type, desc, loc, start, end);
repeats.push_back(&tl_item);

您的代码中唯一的区别是您必须在此声明中使用->而不是.

std::cout << tl_item.getLinkedItems()[0]->toString() << endl;