covariant return type and boost::shared_ptr
2008-03-06 14:53
197 查看
covariant return type and boost::shared_ptr
covariant return type翻译为协变返回值,意义就是在虚函数的返回值上,可以使用子类对象,而不必是基类对象.下面是一个例子:
struct Object
{
public:
virtual ~Object()
{}
};
struct Cloneable: public Object
{
public:
virtual ~Cloneable()
{}
virtual Object* Clone() const = 0;
};
struct Foo : public Cloneable
{
virtual Foo* Clone() const //注意这里
{
return new Foo();
}
};
我们看到Foo的Clone函数返回的是Foo对象,而不是Object对象.显然,C++的这个特点,对于设计继承类层次来说,在某些情况下使用非常方便,因为你不必被强迫使用dynamic_cast或者static_cast来进行类型转换了.
boost::shared_ptr是boost智能指针中最为常用的一个,它是内存资源或者其他资源的正确释放的有力工具. boost::shared_ptr使用在函数返回值当中,也有很好的作用.例如上面的Clone函数的返回值是一个指针,那么这个指针的生命周期的维护就是一个问题.一般来说,这需要使用者和实现者之间有一个很好的协议,这个协议的严格遵守才能保证避免资源的泄露,这个问题也是C++世界中一个非常棘手的问题.引进boost::shared_ptr,可以在很大的程度上解决这个问题,代码如下:
struct Object
{
public:
virtual ~Object()
{}
};
typedef boost::shared_ptr<Object> ObjectPtr;
struct Cloneable: public Object
{
public:
virtual ~Cloneable()
{}
virtual ObjectPtr Clone() const = 0;
};
struct Foo;
typedef boost::shared_ptr<Foo> FooPtr;
struct Foo : public Cloneable
{
virtual FooPtr Clone() const
{
return boost::shared_ptr<Foo>(new Foo());
}
};
资源的释放由智能指针本身维护,用户不必再担心资源的泄露问题.这是一个非常好的方案.
但是,C++的世界不是如此的完美,上面的代码是不能编译成功的,原因是:虽然Object和Foo之间存在继承关系,但是ObjectPtr和FooPtr之间不存在继承关系,这意味着协变返回值在这里不起作用.
为了解决这个问题,在boost的新闻组上http://lists.boost.org/boost-users/2003/02/2996.php 给出了如下的方案(注意这里是针对我们的例子修改以后的):
struct Object
{
public:
virtual ~Object()
{}
};
typedef boost::shared_ptr<Object> ObjectPtr;
struct Cloneable: public Object
{
public:
virtual ~Cloneable()
{}
virtual ObjectPtr DoClone() const = 0;
};
struct Foo;
typedef boost::shared_ptr<Foo> FooPtr;
struct Foo : public Cloneable
{
virtual ObjectPtr DoClone() const
{
return boost::shared_ptr<Foo>(new Foo());
}
FooPtr Clone() const
{
return boost::dynamic_pointer_cast<X>(this-> DoClone ());
}
};
这个方案在一定程度上解决了问题,但是我个人非常不认同这个方案,主要的理由如下:
1. Cloneable类型是一个接口类,一般来说,接口的抽象程度比较高,使用范围也很广.接口一般是用来抽象概念的,上面改变接口函数的做法,在一定的程度上伤害了这个概念.试想,如果你是Cloneable的最初设计者,你会把接口声明为DoClone吗?这种技术妨碍概念设计的做法,是应该竭力避免的.
2. 即便是从纯粹技术的角度说,这种做法也存在问题.上面的例子是两层继承设计,当然在实际中也可能是三层或者更多的层次,我们就以三层为例,为了使用这种技术,还得设定一个新的名称,难道是DoDoClone?!显然,这个的技术会随着层次的加深而越发的不可接受.所以说,这个技术的扩展性比较差.
其实,我认为更好的方法在boost中已经使用,这个方法是:
1) 上层的接口设计保持不变,仍然是从概念出发,例如Cloneable的接口函数名称仍然是Clone,返回值类型是ObjectPtr;
2) 下层的接口直接继承上层的接口,如果是实现类,那么并不使用协变返回值的技术,仍然是返回ObjectPtr;
3) 提供一个模板化的全局函数,实现向上转型.
上面例子的做法是:
struct Object
{
public:
virtual ~Object()
{}
};
typedef boost::shared_ptr<Object> ObjectPtr;
struct Cloneable: public Object
{
public:
virtual ~Cloneable()
{}
virtual ObjectPtr Clone() const = 0;
};
struct Foo;
typedef boost::shared_ptr<Foo> FooPtr;
struct Foo : public Cloneable
{
virtual ObjectPtr Clone() const
{
return ObjectPtr <Foo>(new Foo());
}
};
template<class X> shared_ptr<X> clone(X const & x)
{
shared_ptr<X> px = boost::dynamic_pointer_cast<X>(x.Clone());
assert(px);
return px;
}
其实这里也可以使用boost:: static_pointer_cast.
covariant return type翻译为协变返回值,意义就是在虚函数的返回值上,可以使用子类对象,而不必是基类对象.下面是一个例子:
struct Object
{
public:
virtual ~Object()
{}
};
struct Cloneable: public Object
{
public:
virtual ~Cloneable()
{}
virtual Object* Clone() const = 0;
};
struct Foo : public Cloneable
{
virtual Foo* Clone() const //注意这里
{
return new Foo();
}
};
我们看到Foo的Clone函数返回的是Foo对象,而不是Object对象.显然,C++的这个特点,对于设计继承类层次来说,在某些情况下使用非常方便,因为你不必被强迫使用dynamic_cast或者static_cast来进行类型转换了.
boost::shared_ptr是boost智能指针中最为常用的一个,它是内存资源或者其他资源的正确释放的有力工具. boost::shared_ptr使用在函数返回值当中,也有很好的作用.例如上面的Clone函数的返回值是一个指针,那么这个指针的生命周期的维护就是一个问题.一般来说,这需要使用者和实现者之间有一个很好的协议,这个协议的严格遵守才能保证避免资源的泄露,这个问题也是C++世界中一个非常棘手的问题.引进boost::shared_ptr,可以在很大的程度上解决这个问题,代码如下:
struct Object
{
public:
virtual ~Object()
{}
};
typedef boost::shared_ptr<Object> ObjectPtr;
struct Cloneable: public Object
{
public:
virtual ~Cloneable()
{}
virtual ObjectPtr Clone() const = 0;
};
struct Foo;
typedef boost::shared_ptr<Foo> FooPtr;
struct Foo : public Cloneable
{
virtual FooPtr Clone() const
{
return boost::shared_ptr<Foo>(new Foo());
}
};
资源的释放由智能指针本身维护,用户不必再担心资源的泄露问题.这是一个非常好的方案.
但是,C++的世界不是如此的完美,上面的代码是不能编译成功的,原因是:虽然Object和Foo之间存在继承关系,但是ObjectPtr和FooPtr之间不存在继承关系,这意味着协变返回值在这里不起作用.
为了解决这个问题,在boost的新闻组上http://lists.boost.org/boost-users/2003/02/2996.php 给出了如下的方案(注意这里是针对我们的例子修改以后的):
struct Object
{
public:
virtual ~Object()
{}
};
typedef boost::shared_ptr<Object> ObjectPtr;
struct Cloneable: public Object
{
public:
virtual ~Cloneable()
{}
virtual ObjectPtr DoClone() const = 0;
};
struct Foo;
typedef boost::shared_ptr<Foo> FooPtr;
struct Foo : public Cloneable
{
virtual ObjectPtr DoClone() const
{
return boost::shared_ptr<Foo>(new Foo());
}
FooPtr Clone() const
{
return boost::dynamic_pointer_cast<X>(this-> DoClone ());
}
};
这个方案在一定程度上解决了问题,但是我个人非常不认同这个方案,主要的理由如下:
1. Cloneable类型是一个接口类,一般来说,接口的抽象程度比较高,使用范围也很广.接口一般是用来抽象概念的,上面改变接口函数的做法,在一定的程度上伤害了这个概念.试想,如果你是Cloneable的最初设计者,你会把接口声明为DoClone吗?这种技术妨碍概念设计的做法,是应该竭力避免的.
2. 即便是从纯粹技术的角度说,这种做法也存在问题.上面的例子是两层继承设计,当然在实际中也可能是三层或者更多的层次,我们就以三层为例,为了使用这种技术,还得设定一个新的名称,难道是DoDoClone?!显然,这个的技术会随着层次的加深而越发的不可接受.所以说,这个技术的扩展性比较差.
其实,我认为更好的方法在boost中已经使用,这个方法是:
1) 上层的接口设计保持不变,仍然是从概念出发,例如Cloneable的接口函数名称仍然是Clone,返回值类型是ObjectPtr;
2) 下层的接口直接继承上层的接口,如果是实现类,那么并不使用协变返回值的技术,仍然是返回ObjectPtr;
3) 提供一个模板化的全局函数,实现向上转型.
上面例子的做法是:
struct Object
{
public:
virtual ~Object()
{}
};
typedef boost::shared_ptr<Object> ObjectPtr;
struct Cloneable: public Object
{
public:
virtual ~Cloneable()
{}
virtual ObjectPtr Clone() const = 0;
};
struct Foo;
typedef boost::shared_ptr<Foo> FooPtr;
struct Foo : public Cloneable
{
virtual ObjectPtr Clone() const
{
return ObjectPtr <Foo>(new Foo());
}
};
template<class X> shared_ptr<X> clone(X const & x)
{
shared_ptr<X> px = boost::dynamic_pointer_cast<X>(x.Clone());
assert(px);
return px;
}
其实这里也可以使用boost:: static_pointer_cast.
相关文章推荐
- boost shared_ptr 使用注意点。
- boost::weak_ptr和enable_shared_from_this
- Boost智能指针——shared_ptr
- boost::shared_ptr的使用方法
- boost::shared_ptr递归调用解决办法--boost::enable_shared_from_this
- Boost - shared_ptr
- boost的shared_ptr循环引用(1)
- boost>shared_ptr
- boost的shared_ptr循环引用
- ERROR:shared_ptr does not name a type
- C++学习 boost学习之-shared_ptr
- [zz]boost/shared_ptr 用法总结
- boost shared_ptr 总结
- Boost 关于 shared_ptr 的学习心得
- 关于boost的shared_ptr以及weak_ptr的研究
- boost中的shared_ptr的一些理解
- 【Boost】系列03:内存管理之shared_ptr智能指针
- 将boost::shared_ptr设置为NULL的方法
- Boost源码学习---shared_ptr.hpp
- boost::shared_ptr与ZThread::PoolExecutor联用导致的错误