C++ 管理生命周期
我创建了一个容器来控制某些类型对象的生命周期(新建/删除),以避免任何编程错误。例如,删除对象时不会向容器发出任何通知。这些对象继承自同一基类(GreetingBase) 对于实现,我使用“模板技巧”:C++ 管理生命周期,c++,templates,design-patterns,C++,Templates,Design Patterns,我创建了一个容器来控制某些类型对象的生命周期(新建/删除),以避免任何编程错误。例如,删除对象时不会向容器发出任何通知。这些对象继承自同一基类(GreetingBase) 对于实现,我使用“模板技巧”: class-GreetingBase{ 公众: 虚拟空间sayHello(){ 标准::cout 为此可以使用模板,但使用接收指向基类的指针的函数更好 标准C++11方式-使用static\u assertwith.Without.C++11-boost等价物或您自己的元函数 旁注:如果使用智能
class-GreetingBase{
公众:
虚拟空间sayHello(){
标准::cout
为此可以使用模板
,但使用接收指向基类的指针的函数更好
标准C++11方式-使用static\u assert
with.Without.C++11-boost等价物或您自己的元函数
旁注:如果使用智能指针
,则无需编写此类容器
为此可以使用模板
,但使用接收指向基类的指针的函数更好
标准C++11方式-使用static\u assert
with.Without.C++11-boost等价物或您自己的元函数
旁注:如果您使用智能指针
,则无需编写此类容器我认为将addClass
作为模板没有任何好处;这只意味着您将为每种不同类型实例化一个新的代码副本,并且您正在强制执行特定的构造函数调用
只需将其设置为一个普通函数,并使用基类指针:
void addClass(GreetingBase *o){
items.push_back(o);
}
你的来电者也是
container.addClass( new GreetingDerived() );
而不是
container.addClass<GreetingDerived>();
container.addClass();
我认为将addClass
作为模板没有什么好处;它只是意味着您可以为每种不同的类型实例化一个新的代码副本,并且强制执行一个特定的构造函数调用
只需将其设置为一个普通函数,并使用基类指针:
void addClass(GreetingBase *o){
items.push_back(o);
}
你的来电者也是
container.addClass( new GreetingDerived() );
而不是
container.addClass<GreetingDerived>();
container.addClass();
使用模板来解决这个问题是一种常见的方法吗
我不知道它是否常见,但它看起来足够合理。它确保您的容器只能包含指向使用new
分配的对象的指针,这很好
有什么缺点吗
主要问题是您的容器破坏了。它有一个隐式生成的复制构造函数和复制赋值运算符,只需复制每个指针;这将为您提供两个容器对象,其析构函数都尝试删除相同的对象
解决这一问题的最简单方法是删除这些成员函数,如果您使用的是2011年以前版本的语言,则将其声明为私有(没有实现)。如果您需要能够复制容器,则需要安全地实现它们
就个人而言,我会使用智能指针,而不是滚动我自己的RAII容器;std::unique_ptr
如果容器要具有独占所有权,std::shared_ptr
如果您想要共享所有权,或者可能std::weak_ptr
来保存由共享指针在其他地方管理的对象的非所有权引用在过去的uck中,unique\u ptr
将不可用,但Boost提供了shared\u ptr
,弱\u ptr
,也与您的类似
当“T”不是从“GreetingBase”派生时,报告更好错误消息的任何“标准方式”
在C++11中,您也许可以使用静态断言,例如:
static_assert(std::is_base_of<GreetingBase, T>::value,
"Wrong type for GreetingContainer");
错误消息类似于无法将which*转换为GreetingBase*
,这应该足够清楚
使用模板来解决这个问题是一种常见的方法吗
我不知道它是否常见,但它看起来足够合理。它确保您的容器只能包含指向使用new
分配的对象的指针,这很好
有什么缺点吗
主要问题是您的容器破坏了。它有一个隐式生成的复制构造函数和复制赋值运算符,只需复制每个指针;这将为您提供两个容器对象,其析构函数都尝试删除相同的对象
解决这一问题的最简单方法是删除这些成员函数,如果您使用的是2011年以前版本的语言,则将其声明为私有(没有实现)。如果您需要能够复制容器,则需要安全地实现它们
就个人而言,我会使用智能指针,而不是滚动我自己的RAII容器;std::unique_ptr
如果容器要具有独占所有权,std::shared_ptr
如果您想要共享所有权,或者可能std::weak_ptr
来保存由共享指针在其他地方管理的对象的非所有权引用在过去的uck中,unique\u ptr
将不可用,但Boost提供了shared\u ptr
,弱\u ptr
,也与您的类似
当“T”不是从“GreetingBase”派生时,报告更好错误消息的任何“标准方式”
在C++11中,您也许可以使用静态断言,例如:
static_assert(std::is_base_of<GreetingBase, T>::value,
"Wrong type for GreetingContainer");
错误消息将类似于无法将任何*转换为GreetingBase*
,这应该足够清楚。对于错误报告部分,请使用静态断言
您的GreetingContainer
不遵循,因此如果您复制它,您将得到泄漏。@Xeo我没有将它们放在示例中以保持小规模,但很好的通信nt无论如何,谢谢。对于错误报告部分,请使用static\u assert
您的GreetingContainer
不符合要求,因此如果您复制它,您将得到泄漏。@Xeo我没有将它们放在示例的小范围内,但无论如何都有很好的注释,谢谢。谢谢。我试图避免任何人可以从容器外部删除该实例。任何ggestions?@VíctorHerraiz:就你的代码而言,没有人可以直接访问指针,所以这不是问题。如果你添加了访问器,让它们返回引用或智能指针,而不是原始指针,所以没有人会错误地认为