再谈 Object Factories(对象工厂)

为何而写:

为什么再谈一次,因为上次代码实在是不够好。上篇文章 对象工厂给出的代码太过拙劣,限于学识,我自己类型擦除技术仅仅是把对象的指针转换为void* 而已,实际上可以更为巧妙。这次利用新的类型擦出技术,给出一个完美的解决方,请看下文。

前情描述:

我为什么不直接保存用户提供的function的void*而非要把他copy一份利用容器vector储存起来,然后再去取其指针转换为void*。是因为用户传来的function可能是右值或临时值,一个马上要被删除的值,如果我们直接使用用户提供的function的void*,该指针很可能是悬垂指针。

首先,存储函数遇到了麻烦。因为一个容器只能存储相同类型的元素,所以我其实创建了许多不同类型的静态vector来存储不同类型的function。将vector转换为void*,把vector的void* ,索引值,键值一并将其加入map中。其次,我在注销工厂函数时遇到了更大的麻烦(必须强迫用户出类型标示),因为我们已经失去了存在function容器的类型,同样失去了function具体类型,没有类型信息我无法删除容器中的元素。

就算以上两个问题都不是是问题,这样的代码实现方式真是拙劣。我自己都无法直视。

真正需求:

所以,我们需要一个能储存任何元素的容器,该容器类型唯一,这样我们解决了以上两个麻烦。

其一,我们不在需要创建多个容器,因为这个类型的容器可以储存任何类型的元素。

其二,我们的注销方法不在需要强迫用户给出具体的类型信息,因为容器知道如何删除元素,原因在于容器类型保留下来。

一个能储存任何元素类型的容器,在Java中也许是这样ArrayList<Object>,因为所有类均继承子Object。恩,在C++中如何实现,C++中缺少这样一个父类!

Boost:

早闻boost大名,但一直以为stl都没有完全搞懂,所以不想去研究boost,但boost真的能为我们提供一个可以储存任何类型的容器。他就是boost::any,我这里深入介绍boost::any,把源码贴出来分享给大家。

class any{public: // structorsany() BOOST_NOEXCEPT: content(0){}template<typename ValueType>any(const ValueType & value): content(new holder<BOOST_DEDUCED_TYPENAME remove_cv<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>::type>(value)){}any(const any & other): content(other.content ? other.content->clone() : 0){}#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES// Move constructorany(any&& other) BOOST_NOEXCEPT: content(other.content){other.content = 0;}// Perfect forwarding of ValueTypetemplate<typename ValueType>any(ValueType&& value, typename boost::disable_if<boost::is_same<any&, ValueType> >::type* = 0 // disable if value has type `any&`, typename boost::disable_if<boost::is_const<ValueType> >::type* = 0) // disable if value has type `const ValueType&&`: content(new holder< typename decay<ValueType>::type >(static_cast<ValueType&&>(value))){}#endif~any() BOOST_NOEXCEPT{delete content;}public: // modifiersany & swap(any & rhs) BOOST_NOEXCEPT{std::swap(content, rhs.content);return *this;}#ifdef BOOST_NO_CXX11_RVALUE_REFERENCEStemplate<typename ValueType>any & operator=(const ValueType & rhs){any(rhs).swap(*this);return *this;}any & operator=(any rhs){any(rhs).swap(*this);return *this;}#elseany & operator=(const any& rhs){any(rhs).swap(*this);return *this;}// move assignementany & operator=(any&& rhs) BOOST_NOEXCEPT{rhs.swap(*this);any().swap(rhs);return *this;}// Perfect forwarding of ValueTypetemplate <class ValueType>any & operator=(ValueType&& rhs){any(static_cast<ValueType&&>(rhs)).swap(*this);return *this;}#endifpublic: // queriesbool empty() const BOOST_NOEXCEPT{return !content;}void clear() BOOST_NOEXCEPT{any().swap(*this);}const boost::typeindex::type_info& type() const BOOST_NOEXCEPT{return content ? content->type() : boost::typeindex::type_id<void>().type_info();}#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDSprivate: // types#elsepublic: // types (public so any_cast can be non-friend)#endifclass placeholder{public: // structorsvirtual ~placeholder(){}public: // queriesvirtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT = 0;virtual placeholder * clone() const = 0;};template<typename ValueType>class holder : public placeholder{public: // structorsholder(const ValueType & value): held(value){}#ifndef BOOST_NO_CXX11_RVALUE_REFERENCESholder(ValueType&& value): held(static_cast< ValueType&& >(value)){}#endifpublic: // queriesvirtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT{return boost::typeindex::type_id<ValueType>().type_info();}virtual placeholder * clone() const{return new holder(held);}public: // representationValueType held;private: // intentionally left unimplementedholder & operator=(const holder &);};#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDSprivate: // representationtemplate<typename ValueType>friend ValueType * any_cast(any *) BOOST_NOEXCEPT;template<typename ValueType>friend ValueType * unsafe_any_cast(any *) BOOST_NOEXCEPT;#elsepublic: // representation (public so any_cast can be non-friend)#endifplaceholder * content;};在上述代码中,关键是要理解placeholder和holder,实际上placeholder充当了Java中Object,作为万物的父类。holder是我们的类的一个包装,聚合我们的类对象。而any类持有一个执行包装类的父类指针。另外,在any类的实现这里用到了虚复制构造函数技术。

重头戏,对象工厂:

来吧,先把代码贴上来,talking is cheap,show you the code.

即使爬到最高的山上,一次也只能脚踏实地地迈一步。

再谈 Object Factories(对象工厂)

相关文章:

你感兴趣的文章:

标签云: