2010-02-27 148 views
4

我有一个C++类(在一个dll项目中),其成员变量是boost :: shared_ptrs到其他类的对象。将它们分配给类构造函数还是有一个单独的init()函数可以实现这一点,这会更好吗?在构造函数中分配共享ptrs(boost),单元测试

我假设内部boost :: shared_ptr指针T的默认值为NULL。所以如果我在构造函数里什么都不做,boost :: shared_ptr的get()在调用Init()函数之前返回NULL。

另外,如果在赋值语句中有新的内存分配问题,应该如何捕获异常(在Init中)还是很好地告诉调用者这个Init()来捕获异常? boost :: shared_ptr a(new T);

是否有标准方法来模拟单元测试中的内存分配异常?并查看所有对象已正确取消分配

回答

2

我有一个C++类(在一个dll项目中),其成员变量是boost :: shared_ptrs到其他类的对象。将它们分配给类构造函数还是有一个单独的init()函数可以实现这一点,这会更好吗?

在构造函数中完成所有事情通常更好。
有一个被称为afterwords的init()函数意味着该对象在构造后是无效的,因此您需要保留一个状态标志来指示init()是否已被调用,并在调用任何公用方法时检查该标志并做一些适合未初始化的对象的东西

我假设在boost :: shared_ptr里面的T指针的默认值是NULL。所以如果我在构造函数里什么都不做,boost :: shared_ptr的get()在调用Init()函数之前返回NULL。

是:shared_ptr的默认构造函数将它初始化为NULL。

而且,当有新的内存分配问题的赋值语句,我应该捕获该异常(以初始化)中的一个或者是好讲这个初始化(调用者)来捕捉那会发生什么例外? boost :: shared_ptr a(new T);

如果你有一个构造函数:然后就是已经建成将正确地销毁(通过析构函数),而unitialised对象将不会被感动了所有成员,以及当前对象的内存将被释放,就好像从未被分配过(使用初始化列表的另一个很好的理由)。

如果您使用init():那么您必须捕获异常并正确清理对象并释放内存。根据对象的复杂程度,你可能能够在init中做这件事(但很难做到正确)或者调用者必须这样做。之后,您应该像构造函数抛出异常一样执行相同的操作(这取决于使用情况)。

是否有标准方法来模拟单元测试中的内存分配异常?并看到所有的对象都被正确地解除分配

您可以使用工厂对象来分配对象。
您将工厂对象传递给构造函数。当你想在施工过程中模拟异常时,只需传递一个模拟工厂来生成适当的异常。

1

使用初始化程序列表进行成员分配。他们是首选(有时是唯一的方法)。

如果在创建对象时出现问题,请抛出异常并进行保护。或者,您将需要维护一个valid标志,每次调用成员函数时都必须检查该标志,以检查正在使用的对象是否有效。

你总是可以捕捉异常并报告它们。如果执行失败,理想情况下你不应该抛出异常,而应该在dtor中处理它,报告并继续前进。

1

在第一个问题上,您应该理想地使用初始化列表来确保指针是有效的。不这样做意味着您可能必须始终检查指针在使用前是否有效;特别是如果你把它留给呼叫代码来呼叫init()

另一方面,它可能是你不能这样做,如果他们只能通过调用纯虚拟设置,在这种情况下,你会有使用init()方法。

在初始化时,我认为你可以捕获并重新抛出或者根本不捕获。无论哪种方式,我认为,调用者可以捕获内存分配异常。

我可以看到为什么你想要尝试在你的一个对象上调用init()来测试内存分配异常。这里的一个方法可能是替换一个总是抛出一个调用的存根对象init()

我看不出为什么你想检查共享指针的解除分配(原始指针,也许)当然,共享点指针是,虽然你能够引用你的共享指针,根据定义,共享它,所以它不会被破坏。

也许你可以检查引用计数或设置你的尖锐对象并(在破坏时)清除你的测试可以监控的信号量。我以某种方式错过了这一点?

+0

感谢您的回答罗宾,我应该在单元测试时使用引用计数。我也喜欢创建存根 – Kamal 2010-02-27 15:05:19

+0

@Kamal的想法,如果任何其他初始化成员抛出,编译器将调用任何初始化成员的析构函数。 – 2010-02-27 15:23:35

相关问题