我最后编写了一些代码:
Asteroid *a = new Asteroid( asteroidCollection ) ;
事实证明我不需要变量a
,因为在Asteroid
构造函数中,new Asteroid
最终将自己添加到asteroidCollection
。
所以我最终能写出来了:
new Asteroid( asteroidCollection ) ;
这是不好的风格,考虑到我甚至不需要退货?我应该做到吗
asteroidCollection->createNew() ;
或者
asteroidCollection->add( new Asteroid() ) ;
答案 0 :(得分:8)
我说这是糟糕的风格,因为当你阅读代码时会让人感到困惑。首先想到的是你有内存泄漏。只有在查看构造函数内部并确定对象将其自身添加到某个列表中以便稍后删除之后,混淆才会消失。
还要考虑可能的异常情况。最好将分配的对象存储在某种智能指针中,然后将其添加到集合中。
答案 1 :(得分:5)
对于你的问题,我更喜欢
asteroidCollection->add( new Asteroid() ) ;
比其他两种风格。
它比第一个更好,因为new Asteroid( asteroidCollection ) ;
并不比
Foo( barCollection );
其中Foo是一个类,你在它的构造函数中new
一个Bar对象并将它添加到一个集合中,它太模糊了,不知道发生了什么。
它也比第二个更好,因为IMO asteroidCollection
不应该关心如何创建一个Asteroid
,它是一个集合,所以集合所做的事情。
答案 2 :(得分:1)
风格问题总是有点主观。所以在某些方面我有点像回答它们。这是我的2美分......
请稍等一下,您希望能够创建派生自Asteroid
的对象并将其添加到您的集合中。如果add()
方法恰好调用可能(或使用)虚函数的Asteroid
上的任何函数,那么您可以自己开启访问尚未完全构造的对象的可能性。 / p>
我认为,在构造函数中执行这样的操作会让人感到困惑,并让用户了解正在发生的事情。
我更愿意做一个简单的功能。它甚至不必成为班级的一部分......
Asteroid *CreateAsteroid( AsteroidCollection *coll )
{
Asteroid * a = new Asteroid();
coll->add(a);
return a;
}
如果您确实希望继续使用构造函数方法,那么至少可以将原始代码行放在此函数中,并使用非常明确的描述来对其进行评论。
基本上,尽量不要在幕后做有趣的事情。如果这是不可避免的(或者在某种程度上是可取的),尽量不要强迫编码人员理解这种古怪,无论编码器是你还是其他人。
至少在这种情况下,它并不是那个很奇怪。事情可能会更糟! =)
只是拿你最后两个例子......
asteroidCollection->createNew();
asteroidCollection->add( new Asteroid() );
我认为1号是好的,如果你知道它总是创建一种类型的Asteroid
,并且你不希望你班级的用户担心它。如果无法在集合之间共享Asteroid
,则执行此操作是有意义的。这与我建议的函数类似,但有点使集合类提供可能不应该支持的代码。
如果您可以存储派生的Asteroid
类型,或者如果您希望在将小行星添加到集合之前对其进行特殊处理,则数字2非常有用。这是所有三种方法中最灵活的。
答案 3 :(得分:0)
这看起来真的有问题,谁管理小行星的寿命?
它是否真的在小行星的用户和集合之间共享,如果是这样的话,你应该对小行星有一个shared_ptr,以便最后一个拥有它的人清理它。
如果没有将小行星放入小行星集合中就不可能创建小行星,那么该集合就拥有了它的生命周期。
如果在堆栈上创建小行星会发生什么?如果我将该小行星固定在unique_ptr或shared_ptr而不是直接调用new,会发生什么,例如:
auto asteroid = std::make_shared(asteroidCollection)
会被删除两次吗?
如果你不希望任何人对小行星做任何事情,那么对于小行星集合,createAsteroid或addAsteroid的方法可能更合适。简单地调用createNew方法听起来就像是在创建一个新的AsteroidCollection,我认为这不是你想要的。