两种技术相比的优缺点是什么?更重要的是:为什么和何时应该使用其中之一?这只是个人口味/偏好的问题吗?
据我所知,我没有找到另一个明确回答我的问题的帖子。在许多关于多态性和/或类型抹除实际使用的问题中,以下问题似乎最接近,但它也没有真正回答我的问题:
请注意,我非常理解这两种技术。为此,下面我提供了一个简单的、自包含的工作示例,如果认为没有必要,我很乐意删除它。但是,该示例应该澄清这两种技术在我的问题中的含义。我不感兴趣讨论命名规范。另外,我知道编译时多态和运行时多态之间的区别,尽管我不认为这与问题相关。请注意,如果有任何性能差异,我的兴趣不在于性能差异。然而,如果有一个明显的基于性能的论据支持其中一种方法,我会很想看看。特别是,我想听听具体例子(没有代码),这些例子只适用于其中一种方法。从下面的示例来看,一个主要的区别是内存管理,对于多态而言,内存管理留给用户处理,而对于类型抹除而言,则可以整洁地处理需要一些引用计数(或boost)。话虽如此,根据使用场景的不同,通过使用智能指针结合vector,多态示例的情况可能会得到改进,但是对于任意情况来说,这很可能会变得不切实际。另一个方面,可能有利于类型抹除的是通用接口的独立性,但是这究竟是什么优势呢?
以下代码已经测试(编译和运行)通过MS VisualStudio 2008,只需将所有以下代码块放入单个源文件中即可。我希望它也可以在Linux上使用gcc编译,因为我认为没有理由不行。我在此处分割/划分代码以便清晰易懂。
这些头文件应该足够了,对吧?
#include <iostream>
#include <vector>
#include <string>
简单的引用计数,避免使用boost(或其他)依赖。这个类只在下面的类型抹除示例中使用。
class RefCount
{
RefCount( const RefCount& );
RefCount& operator= ( const RefCount& );
int m_refCount;
public:
RefCount() : m_refCount(1) {}
void Increment() { ++m_refCount; }
int Decrement() { return --m_refCount; }
};
这是一个简单的类型抹除示例/说明。它部分地从以下文章中复制并修改。主要我尽可能使其清晰明了。http://www.cplusplus.com/articles/oz18T05o/
class Object {
struct ObjectInterface {
virtual ~ObjectInterface() {}
virtual std::string GetSomeText() const = 0;
};
template< typename T > struct ObjectModel : ObjectInterface {
ObjectModel( const T& t ) : m_object( t ) {}
virtual ~ObjectModel() {}
virtual std::string GetSomeText() const { return m_object.GetSomeText(); }
T m_object;
};
void DecrementRefCount() {
if( mp_refCount->Decrement()==0 ) {
delete mp_refCount; delete mp_objectInterface;
mp_refCount = NULL; mp_objectInterface = NULL;
}
}
Object& operator= ( const Object& );
ObjectInterface *mp_objectInterface;
RefCount *mp_refCount;
public:
template< typename T > Object( const T& obj )
: mp_objectInterface( new ObjectModel<T>( obj ) ), mp_refCount( new RefCount ) {}
~Object() { DecrementRefCount(); }
std::string GetSomeText() const { return mp_objectInterface->GetSomeText(); }
Object( const Object &obj ) {
obj.mp_refCount->Increment(); mp_refCount = obj.mp_refCount;
mp_objectInterface = obj.mp_objectInterface;
}
};
struct MyObject1 { std::string GetSomeText() const { return "MyObject1"; } };
struct MyObject2 { std::string GetSomeText() const { return "MyObject2"; } };
void UseTypeErasure() {
typedef std::vector<Object> ObjVect;
typedef ObjVect::const_iterator ObjVectIter;
ObjVect objVect;
objVect.push_back( Object( MyObject1() ) );
objVect.push_back( Object( MyObject2() ) );
for( ObjVectIter iter = objVect.begin(); iter != objVect.end(); ++iter )
std::cout << iter->GetSomeText();
}
据我所知,这似乎可以通过多态来实现相同的功能,或者也许不是?
struct ObjectInterface {
virtual ~ObjectInterface() {}
virtual std::string GetSomeText() const = 0;
};
struct MyObject3 : public ObjectInterface {
std::string GetSomeText() const { return "MyObject3"; } };
struct MyObject4 : public ObjectInterface {
std::string GetSomeText() const { return "MyObject4"; } };
void UsePolymorphism() {
typedef std::vector<ObjectInterface*> ObjVect;
typedef ObjVect::const_iterator ObjVectIter;
ObjVect objVect;
objVect.push_back( new MyObject3 );
objVect.push_back( new MyObject4 );
for( ObjVectIter iter = objVect.begin(); iter != objVect.end(); ++iter )
std::cout << (*iter)->GetSomeText();
for( ObjVectIter iter = objVect.begin(); iter != objVect.end(); ++iter )
delete *iter;
}
最后,为了测试上述所有内容的有效性。
int main() {
UseTypeErasure();
UsePolymorphism();
return(0);
}
poly
类或者Boost.TypeErasure(已通过但尚未发布)?除了CRTP之外,它们实现了“基于概念”的多态性,具有适当的值语义。 - J.N.std :: shared_ptr <T>
、std :: function
或boost :: any
,则使用类型擦除。其余请在编译时完成。 - Kerrek SBclass Object
开头的代码都是可疑的 :-).) - Kerrek SB